Skip to content

Commit d12abbd

Browse files
committed
Add a 'shortcut' to conversion check
This is an approximate check of arguments - if we can find an argument that differs at the head, there's no point in checking further. This can be a significant shortcut when conversion checking two large terms that only differ very slightly, as it saves checking big arguments unnecessarily.
1 parent 5aba3b4 commit d12abbd

File tree

1 file changed

+47
-4
lines changed

1 file changed

+47
-4
lines changed

src/Core/Normalise.idr

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -883,14 +883,57 @@ tryUpdate ms (Erased fc i) = pure $ Erased fc i
883883
tryUpdate ms (TType fc) = pure $ TType fc
884884

885885
mutual
886+
allConvNF : {auto c : Ref Ctxt Defs} ->
887+
{vars : _} ->
888+
Ref QVar Int -> Defs -> Env Term vars ->
889+
List (NF vars) -> List (NF vars) -> Core Bool
890+
allConvNF q defs env [] [] = pure True
891+
allConvNF q defs env (x :: xs) (y :: ys)
892+
= do ok <- allConvNF q defs env xs ys
893+
if ok then convGen q defs env x y
894+
else pure False
895+
allConvNF q defs env _ _ = pure False
896+
897+
-- return False if anything differs at the head, to quickly find
898+
-- conversion failures without going deeply into all the arguments.
899+
-- True means they might still match
900+
quickConv : List (NF vars) -> List (NF vars) -> Bool
901+
quickConv [] [] = True
902+
quickConv (x :: xs) (y :: ys) = quickConvArg x y && quickConv xs ys
903+
where
904+
quickConvHead : NHead vars -> NHead vars -> Bool
905+
quickConvHead (NLocal _ _ _) (NLocal _ _ _) = True
906+
quickConvHead (NRef _ n) (NRef _ n') = n == n'
907+
quickConvHead (NMeta n _ _) (NMeta n' _ _) = n == n'
908+
quickConvHead _ _ = False
909+
910+
quickConvArg : NF vars -> NF vars -> Bool
911+
quickConvArg (NBind{}) _ = True -- let's not worry about eta here...
912+
quickConvArg _ (NBind{}) = True
913+
quickConvArg (NApp _ h _) (NApp _ h' _) = quickConvHead h h'
914+
quickConvArg (NDCon _ _ t _ _) (NDCon _ _ t' _ _) = t == t'
915+
quickConvArg (NTCon _ n _ _ _) (NTCon _ n' _ _ _) = n == n'
916+
quickConvArg (NAs _ _ _ t) (NAs _ _ _ t') = quickConvArg t t'
917+
quickConvArg (NDelayed _ _ t) (NDelayed _ _ t') = quickConvArg t t'
918+
quickConvArg (NDelay _ _ _ _) (NDelay _ _ _ _) = True
919+
quickConvArg (NForce _ _ t _) (NForce _ _ t' _) = quickConvArg t t'
920+
quickConvArg (NPrimVal _ c) (NPrimVal _ c') = c == c'
921+
quickConvArg (NType _) (NType _) = True
922+
quickConvArg (NErased _ _) _ = True
923+
quickConvArg _ (NErased _ _) = True
924+
quickConvArg _ _ = False
925+
quickConv _ _ = False
926+
886927
allConv : {auto c : Ref Ctxt Defs} ->
887928
{vars : _} ->
888929
Ref QVar Int -> Defs -> Env Term vars ->
889930
List (Closure vars) -> List (Closure vars) -> Core Bool
890-
allConv q defs env [] [] = pure True
891-
allConv q defs env (x :: xs) (y :: ys)
892-
= pure $ !(convGen q defs env x y) && !(allConv q defs env xs ys)
893-
allConv q defs env _ _ = pure False
931+
allConv q defs env xs ys
932+
= do xsnf <- traverse (evalClosure defs) xs
933+
ysnf <- traverse (evalClosure defs) ys
934+
if quickConv xsnf ysnf
935+
then allConvNF q defs env xsnf ysnf
936+
else pure False
894937

895938
-- If the case trees match in structure, get the list of variables which
896939
-- have to match in the call

0 commit comments

Comments
 (0)