@@ -14,11 +14,13 @@ import Idris.Providers
14import Idris.Primitives
14import Idris.Primitives
15import Idris.Inliner
15import Idris.Inliner
16import Idris.PartialEval
16import Idris.PartialEval
17+import Idris.Transforms
17import Idris.DeepSeq
18import Idris.DeepSeq
18import Idris.Output (iputStrLn, pshow, iWarn)
19import Idris.Output (iputStrLn, pshow, iWarn)
19import IRTS.Lang
20import IRTS.Lang
21import Idris.Elab.Type
22import Idris.Elab.Type
23+import Idris.Elab.Transform
22import Idris.Elab.Utils
24import Idris.Elab.Utils
24import Idris.Core.TT
26import Idris.Core.TT
@@ -48,6 +50,7 @@ import Data.Char(isLetter, toLower)
48import Data.List.Split (splitOn)
50import Data.List.Split (splitOn)
50import Util.Pretty(pretty, text)
52import Util.Pretty(pretty, text)
52-- | Elaborate a collection of left-hand and right-hand pairs - that is, a
55-- | Elaborate a collection of left-hand and right-hand pairs - that is, a
53-- top-level definition.
56-- top-level definition.
@@ -81,13 +84,25 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
81 addIBC (IBCOpt n)
84 addIBC (IBCOpt n)
83 ist <- getIState
86 ist <- getIState
87+ let tpats = transformPats ist pats_in
84− let pats = map (simple_lhs (tt_ctxt ist)) $ doTransforms ist pats_in
88+ let pats = map (simple_lhs (tt_ctxt ist)) $
89+ doPartialEval ist tpats
86 -- logLvl 3 (showSep "\n" (map (\ (l,r) ->
91 -- logLvl 3 (showSep "\n" (map (\ (l,r) ->
87 -- show l ++ " = " ++
92 -- show l ++ " = " ++
88 -- show r) pats))
93 -- show r) pats))
89 let tcase = opt_typecase (idris_options ist)
94 let tcase = opt_typecase (idris_options ist)
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
101+ Right (l, r) -> elabPE info fc n r) pats
103+ -- Redo transforms with the newly generated transformations
104+ let pats_transformed = transformPats ist pats
91 -- Summary of what's about to happen: Definitions go:
106 -- Summary of what's about to happen: Definitions go:
93 -- pats_in -> pats -> pdef -> pdef'
108 -- pats_in -> pats -> pdef -> pdef'
@@ -97,18 +112,11 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
97 -- pdef is the compile-time pattern definition.
112 -- pdef is the compile-time pattern definition.
98 -- This will get further optimised for run-time, and, separately,
113 -- This will get further optimised for run-time, and, separately,
99 -- further inlined to help with totality checking.
114 -- further inlined to help with totality checking.
100− let pdef = map debind pats
115+ let pdef = map debind pats_transformed
102 logLvl 5 $ "Initial typechecked patterns:\n" ++ show pats
117 logLvl 5 $ "Initial typechecked patterns:\n" ++ show pats
103 logLvl 5 $ "Initial typechecked pattern def:\n" ++ show pdef
118 logLvl 5 $ "Initial typechecked pattern def:\n" ++ show pdef
105− -- Look for 'static' names and generate new specialised
106− -- definitions for them
108− mapM_ (\ e -> case e of
110− Right (l, r) -> elabPE info fc n r) pats
112 -- NOTE: Need to store original definition so that proofs which
120 -- NOTE: Need to store original definition so that proofs which
113 -- rely on its structure aren't affected by any changes to the
121 -- rely on its structure aren't affected by any changes to the
114 -- inliner. Just use the inlined version to generate pdef' and to
122 -- 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
120 numArgs <- tclift $ sameLength pdef
128 numArgs <- tclift $ sameLength pdef
122 case specNames opts of
130 case specNames opts of
123− Just _ -> logLvl 5 $ "Partially evaluated:\n" ++ show pats
131+ Just _ -> logLvl 1 $ "Partially evaluated:\n" ++ show pats
124 _ -> return ()
132 _ -> return ()
126 erInfo <- getErasureInfo <$> getIState
134 erInfo <- getErasureInfo <$> getIState
@@ -163,7 +171,6 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
163 -- then case tot of
171 -- then case tot of
164 -- Total _ -> return ()
172 -- Total _ -> return ()
165 -- t -> tclift $ tfail (At fc (Msg (show n ++ " is " ++ show t)))
173 -- t -> tclift $ tfail (At fc (Msg (show n ++ " is " ++ show t)))
167 -- _ -> return ()
174 -- _ -> return ()
168 case tree of
175 case tree of
169 CaseDef _ _ [] -> return ()
176 CaseDef _ _ [] -> return ()
@@ -271,9 +278,8 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
271 else tfail (At fc (Msg "Clauses have differing numbers of arguments "))
278 else tfail (At fc (Msg "Clauses have differing numbers of arguments "))
272 sameLength [] = return 0
279 sameLength [] = return 0
274− -- apply all transformations (just specialisation for now, add
281+ -- Partially evaluate, if the definition is marked as specialisable
275− -- user defined transformation rules later)
282+ doPartialEval ist pats =
276− doTransforms ist pats =
277 case specNames opts of
283 case specNames opts of
278 Nothing -> pats
284 Nothing -> pats
279 Just ns -> partial_eval (tt_ctxt ist) ns pats
285 Just ns -> partial_eval (tt_ctxt ist) ns pats
@@ -285,38 +291,45 @@ elabPE info fc caller r =
285 let sa = getSpecApps ist [] r
291 let sa = getSpecApps ist [] r
286 mapM_ (mkSpecialised ist) sa
292 mapM_ (mkSpecialised ist) sa
294+ -- Make a specialised version of the application, and
288− -- TODO: Add a PTerm level transformation rule, which is basically the
295+ -- add a PTerm level transformation rule, which is basically the
289 -- new definition in reverse (before specialising it).
296 -- new definition in reverse (before specialising it).
290 -- RHS => LHS where implicit arguments are left blank in the
297 -- RHS => LHS where implicit arguments are left blank in the
291 -- transformation.
298 -- transformation.
293− -- Apply that transformation after every PClauses elaboration
300+ -- Transformation rules are applied after every PClause elaboration
295 mkSpecialised ist specapp_in = do
302 mkSpecialised ist specapp_in = do
296 let (specTy, specapp) = getSpecTy ist specapp_in
303 let (specTy, specapp) = getSpecTy ist specapp_in
297− let (n, newnm, pats) = getSpecClause ist specapp
304+ let (n, newnm, (lhs, rhs)) = getSpecClause ist specapp
298 let undef = case lookupDef newnm (tt_ctxt ist) of
305 let undef = case lookupDef newnm (tt_ctxt ist) of
299 [] -> True
306 [] -> True
300 _ -> False
307 _ -> False
301− logLvl 5 $ show (newnm, map (concreteArg ist) (snd specapp))
308+ logLvl 3 $ show (newnm, map (concreteArg ist) (snd specapp))
302 idrisCatch
309 idrisCatch
303 (when (undef && all (concreteArg ist) (snd specapp)) $ do
310 (when (undef && all (concreteArg ist) (snd specapp)) $ do
304 cgns <- getAllNames n
311 cgns <- getAllNames n
305 let opts = [Specialise (map (\x -> (x, Nothing)) cgns ++
312 let opts = [Specialise (map (\x -> (x, Nothing)) cgns ++
306 mapMaybe specName (snd specapp))]
313 mapMaybe specName (snd specapp))]
307 logLvl 3 $ "Specialising application: " ++ show specapp
314 logLvl 3 $ "Specialising application: " ++ show specapp
315+ ++ " with " ++ show cgns
308− logLvl 2 $ "New name: " ++ show newnm
316+ logLvl 3 $ "New name: " ++ show newnm
309− iLOG $ "PE definition type : " ++ (show specTy)
317+ logLvl 3 $ "PE definition type : " ++ (show specTy)
310 ++ "\n" ++ show opts
318 ++ "\n" ++ show opts
311− logLvl 2 $ "PE definition " ++ show newnm ++ ":\n" ++
319+ logLvl 3 $ "PE definition " ++ show newnm ++ ":\n" ++
312− showSep "\n"
320+-- showSep "\n"
313− (map (\ (lhs, rhs) ->
321+-- (map (\ (lhs, rhs) ->
314 (showTmImpls lhs ++ " = " ++
322 (showTmImpls lhs ++ " = " ++
315− showTmImpls rhs)) pats)
323+ showTmImpls rhs) -- pats)
325+ logLvl 2 $ show n ++ " transformation rule: " ++
326+ show rhs ++ " ==> " ++ show lhs
316 elabType info defaultSyntax emptyDocstring [] fc opts newnm specTy
328 elabType info defaultSyntax emptyDocstring [] fc opts newnm specTy
329+ elabTransform info fc False rhs lhs
330+ let def = -- map (\ (lhs, rhs) ->
317− let def = map (\ (lhs, rhs) -> PClause fc newnm lhs [] rhs []) pats
331+ [PClause fc newnm lhs [] rhs []] --) pats
318− elabClauses info fc opts newnm def
332+ elabClauses info fc opts newnm def)
319− logLvl 2 $ "Specialised " ++ show newnm)
320 -- if it doesn't work, just don't specialise. Could happen for lots
333 -- if it doesn't work, just don't specialise. Could happen for lots
321 -- of valid reasons (e.g. local variables in scope which can't be
334 -- of valid reasons (e.g. local variables in scope which can't be
322 -- lifted out).
335 -- lifted out).
@@ -351,14 +364,20 @@ elabPE info fc caller r =
352 -- get the clause of a specialised application
365 -- get the clause of a specialised application
353 getSpecClause ist (n, args)
366 getSpecClause ist (n, args)
354− = let newnm = sUN ("__"++show (nsroot n) ++ "_" ++
367+ = let newnm = sUN ("PE_"++show (nsroot n) ++ "_" ++
355− showSep "_" (map showArg args)) in
368+ qhash 0 (showSep "_" (map showArg args))) in
356 -- UN (show n ++ show (map snd args)) in
369 -- UN (show n ++ show (map snd args)) in
357 (n, newnm, mkPE_TermDecl ist newnm n args)
370 (n, newnm, mkPE_TermDecl ist newnm n args)
358 where showArg (ExplicitS, n) = show n
371 where showArg (ExplicitS, n) = show n
359 showArg (ImplicitS, n) = show n
372 showArg (ImplicitS, n) = show n
360 showArg _ = ""
373 showArg _ = ""
375+ -- TMP for readability! This is obviously a really bad hashing
377+ qhash :: Int -> String -> String
378+ qhash acc [] = showHex acc ""
379+ qhash acc (x:xs) = qhash (fromEnum x + acc) xs
362-- checks if the clause is a possible left hand side. Returns the term if
381-- checks if the clause is a possible left hand side. Returns the term if
363-- possible, otherwise Nothing.
382-- possible, otherwise Nothing.