@@ -59,6 +59,8 @@ elabClauses :: ElabInfo -> FC -> FnOpts -> Name -> [PClause] -> Idris ()
59elabClauses info fc opts n_in cs = let n = liftname info n_in in
59elabClauses info fc opts n_in cs = let n = liftname info n_in in
60 do ctxt <- getContext
60 do ctxt <- getContext
61 ist <- getIState
61 ist <- getIState
62+ optimise <- getOptimise
63+ let petrans = PETransform `elem` optimise
62 inacc <- map fst <$> fgetState (opt_inaccessible . ist_optimisation n)
64 inacc <- map fst <$> fgetState (opt_inaccessible . ist_optimisation n)
64 -- Check n actually exists, with no definition yet
66 -- Check n actually exists, with no definition yet
@@ -74,9 +76,11 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
74 let atys = map snd (getArgTys fty)
76 let atys = map snd (getArgTys fty)
75 cs_elab <- mapM (elabClause info opts)
77 cs_elab <- mapM (elabClause info opts)
76 (zip [0..] cs)
78 (zip [0..] cs)
79+ -- pats_raw is the version we'll work with at compile time:
80+ -- no simplification or PE
77 let (pats_in, cs_full) = unzip cs_elab
81 let (pats_in, cs_full) = unzip cs_elab
78−
82+ let pats_raw = map (simple_lhs (tt_ctxt ist)) pats_in
79− logLvl 3 $ "Elaborated patterns:\n" ++ show pats_in
83+ logLvl 3 $ "Elaborated patterns:\n" ++ show pats_raw
81 solveDeferred n
85 solveDeferred n
@@ -94,22 +98,28 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
94 -- If the definition is specialisable, this reduces the
98 -- If the definition is specialisable, this reduces the
96 pe_tm <- doPartialEval ist tpats
100 pe_tm <- doPartialEval ist tpats
101+ let pats_pe = if petrans
97− let pats = map (simple_lhs (tt_ctxt ist)) pe_tm
102+ then map (simple_lhs (tt_ctxt ist)) pe_tm
99 let tcase = opt_typecase (idris_options ist)
105 let tcase = opt_typecase (idris_options ist)
101 -- Look for 'static' names and generate new specialised
107 -- Look for 'static' names and generate new specialised
102 -- definitions for them, as well as generating rewrite rules
108 -- definitions for them, as well as generating rewrite rules
103 -- for partially evaluated definitions
109 -- for partially evaluated definitions
110+ newrules <- if petrans
104− newrules <- mapM (\ e -> case e of
111+ then mapM (\ e -> case e of
105− Left _ -> return []
112+ Left _ -> return []
106− Right (l, r) -> elabPE info fc n r) pats
113+ Right (l, r) -> elabPE info fc n r) pats_pe
108 -- Redo transforms with the newly generated transformations, so
116 -- Redo transforms with the newly generated transformations, so
109 -- that the specialised application we've just made gets
117 -- that the specialised application we've just made gets
110 -- used in place of the general one
118 -- used in place of the general one
111 ist <- getIState
119 ist <- getIState
112− let pats_transformed = transformPats ist pats
120+ let pats_transformed = if petrans
121+ then transformPats ist pats_pe
114 -- Summary of what's about to happen: Definitions go:
124 -- Summary of what's about to happen: Definitions go:
@@ -118,11 +128,13 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
118 -- addCaseDef builds case trees from <pdef> and <pdef'>
128 -- addCaseDef builds case trees from <pdef> and <pdef'>
120 -- pdef is the compile-time pattern definition.
130 -- pdef is the compile-time pattern definition.
121− -- This will get further optimised for run-time, and, separately,
122− -- further inlined to help with totality checking.
131+ -- This will get further inlined to help with totality checking.
123− let pdef = map debind pats_transformed
132+ let pdef = map debind pats_raw
133+ -- pdef_pe is the one which will get further optimised
134+ -- for run-time, and, partially evaluated
135+ let pdef_pe = map debind pats_transformed
125− logLvl 5 $ "Initial typechecked patterns:\n" ++ show pats
137+ logLvl 5 $ "Initial typechecked patterns:\n" ++ show pats_raw
126 logLvl 5 $ "Initial typechecked pattern def:\n" ++ show pdef
138 logLvl 5 $ "Initial typechecked pattern def:\n" ++ show pdef
128 -- NOTE: Need to store original definition so that proofs which
140 -- NOTE: Need to store original definition so that proofs which
@@ -137,13 +149,13 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
138 case specNames opts of
150 case specNames opts of
139 Just _ ->
151 Just _ ->
140− do logLvl 2 $ "Partially evaluated:\n" ++ show pats
152+ do logLvl 2 $ "Partially evaluated:\n" ++ show pats_pe
141 logLvl 2 $ "Transformed:\n" ++ show pats_transformed
153 logLvl 2 $ "Transformed:\n" ++ show pats_transformed
142 _ -> return ()
154 _ -> return ()
144 erInfo <- getErasureInfo <$> getIState
156 erInfo <- getErasureInfo <$> getIState
145 tree@(CaseDef scargs sc _) <- tclift $
157 tree@(CaseDef scargs sc _) <- tclift $
146− simpleCase tcase False reflect CompileTime fc inacc atys pdef erInfo
158+ simpleCase tcase False reflect CompileTime fc inacc atys pdef erInfo
147 cov <- coverage
159 cov <- coverage
148 pmissing <-
160 pmissing <-
149 if cov && not (hasDefault cs)
161 if cov && not (hasDefault cs)
@@ -164,8 +176,9 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
164 else return []
176 else return []
165 let pcover = null pmissing
177 let pcover = null pmissing
167− -- pdef' is the version that gets compiled for run-time
179+ -- pdef' is the version that gets compiled for run-time,
180+ -- so we start from the partially evaluated version
168− pdef_in' <- applyOpts pdef
181+ pdef_in' <- applyOpts pdef_pe
169 let pdef' = map (simple_rt (tt_ctxt ist)) pdef_in'
182 let pdef' = map (simple_rt (tt_ctxt ist)) pdef_in'
171 logLvl 5 $ "After data structure transformations:\n" ++ show pdef'
184 logLvl 5 $ "After data structure transformations:\n" ++ show pdef'
@@ -197,7 +210,7 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
197 ctxt <- getContext
210 ctxt <- getContext
198 ist <- getIState
211 ist <- getIState
199 let opt = idris_optimisation ist
212 let opt = idris_optimisation ist
200− putIState (ist { idris_patdefs = addDef n (force pdef, force pmissing)
213+ putIState (ist { idris_patdefs = addDef n (force pdef_pe, force pmissing)
201 (idris_patdefs ist) })
214 (idris_patdefs ist) })
202 let caseInfo = CaseInfo (inlinable opts) (dictionary opts)
215 let caseInfo = CaseInfo (inlinable opts) (dictionary opts)
203 case lookupTy n ctxt of
216 case lookupTy n ctxt of
@@ -207,8 +220,11 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
207 (AssertTotal `elem` opts)
220 (AssertTotal `elem` opts)
225+ pdef -- compile time
211− pdef pdef pdef_inl pdef' ty)
226+ pdef_inl -- inlined
212 addIBC (IBCDef n)
228 addIBC (IBCDef n)
213 setTotality n tot
229 setTotality n tot
214 when (not reflect) $ do totcheck (fc, n)
230 when (not reflect) $ do totcheck (fc, n)
@@ -320,7 +336,8 @@ elabPE info fc caller r =
320 let cgns' = filter (/= n) cgns
336 let cgns' = filter (/= n) cgns
321 let opts = [Specialise (map (\x -> (x, Nothing)) cgns' ++
337 let opts = [Specialise (map (\x -> (x, Nothing)) cgns' ++
322 (n, Just 65536) :
338 (n, Just 65536) :
339+ mapMaybe (specName (pe_simple specdecl))
323− mapMaybe specName (snd specapp))]
340+ (snd specapp))]
324 logLvl 3 $ "Specialising application: " ++ show specapp
341 logLvl 3 $ "Specialising application: " ++ show specapp
325 ++ " in " ++ show caller ++
342 ++ " in " ++ show caller ++
326 " with " ++ show opts
343 " with " ++ show opts
@@ -347,14 +364,14 @@ elabPE info fc caller r =
347 -- if it doesn't work, just don't specialise. Could happen for lots
364 -- if it doesn't work, just don't specialise. Could happen for lots
348 -- of valid reasons (e.g. local variables in scope which can't be
365 -- of valid reasons (e.g. local variables in scope which can't be
349 -- lifted out).
366 -- lifted out).
350− (\e -> do logLvl 4 $ "Couldn't specialise: " ++ (pshow ist e)
367+ (\e -> do logLvl 3 $ "Couldn't specialise: " ++ (pshow ist e)
351 return [])
368 return [])
353− specName (ImplicitS, tm)
370+ specName simpl (ImplicitS, tm)
354− | (P Ref n _, _) <- unApply tm = Just (n, Just 1)
371+ | (P Ref n _, _) <- unApply tm = Just (n, Just (if simpl then 1 else 0))
355− specName (ExplicitS, tm)
372+ specName simpl (ExplicitS, tm)
356− | (P Ref n _, _) <- unApply tm = Just (n, Just 1)
373+ | (P Ref n _, _) <- unApply tm = Just (n, Just (if simpl then 1 else 0))
357− specName _ = Nothing
374+ specName simpl _ = Nothing
359 concreteArg ist (ImplicitS, tm) = concreteTm ist tm
376 concreteArg ist (ImplicitS, tm) = concreteTm ist tm
360 concreteArg ist (ExplicitS, tm) = concreteTm ist tm
377 concreteArg ist (ExplicitS, tm) = concreteTm ist tm