@@ -5,7 +5,7 @@ Description : Coordinates the compilation process.
5License : BSD3
5License : BSD3
6Maintainer : The Idris Community.
6Maintainer : The Idris Community.
8−{-# LANGUAGE CPP, FlexibleContexts, PatternGuards, TypeSynonymInstances, NamedFieldPuns #-}
8+{-# LANGUAGE CPP, FlexibleContexts, PatternGuards, TypeSynonymInstances, NamedFieldPuns, MultiWayIf #-}
10module IRTS.Compiler(compile, generate) where
10module IRTS.Compiler(compile, generate) where
@@ -255,7 +255,6 @@ type Vars = M.Map Name VarInfo
255irTerm :: Name -> Vars -> [Name] -> Term -> Idris LExp
255irTerm :: Name -> Vars -> [Name] -> Term -> Idris LExp
256irTerm top vs env tm@(App _ f a) = do
256irTerm top vs env tm@(App _ f a) = do
257 ist <- getIState
257 ist <- getIState
258− let (likeNatZ, likeNatS) = getNatLikeCtors ist
259 case unApply tm of
258 case unApply tm of
260 (P _ n _, args)
259 (P _ n _, args)
261 | n `elem` map fst (idris_metavars ist) \\ primDefs
260 | n `elem` map fst (idris_metavars ist) \\ primDefs
@@ -396,11 +395,11 @@ irTerm top vs env tm@(App _ f a) = do
396 -> irTerm top vs env (head argsPruned)
395 -> irTerm top vs env (head argsPruned)
398 -- compile Nat-likes as bigints
397 -- compile Nat-likes as bigints
399− | n `S.member` likeNatZ
398+ | Just LikeZ <- isLikeNat ist n
400 -> irTerm top vs env $ Constant (BI 0)
399 -> irTerm top vs env $ Constant (BI 0)
402 -- compile Nat-likes as bigints
401 -- compile Nat-likes as bigints
403− | n `S.member` likeNatS
402+ | Just LikeS <- isLikeNat ist n
404 -> irTerm top vs env $
403 -> irTerm top vs env $
405 App Complete (P Ref (sUN "prim__addBigInt") Erased) (Constant $ BI 1)
404 App Complete (P Ref (sUN "prim__addBigInt") Erased) (Constant $ BI 1)
@@ -417,7 +416,7 @@ irTerm top vs env tm@(App _ f a) = do
417 -> return . padLams $ \[vn] -> LApp False (LV n) [LV vn]
416 -> return . padLams $ \[vn] -> LApp False (LV n) [LV vn]
419 -- compile Nat-likes as bigints
418 -- compile Nat-likes as bigints
420− | n `S.member` likeNatS
419+ | Just LikeS <- isLikeNat ist n
421 -> irTerm top vs env $
420 -> irTerm top vs env $
422 App Complete (P Ref (sUN "prim__addBigInt") Erased) (Constant $ BI 1)
421 App Complete (P Ref (sUN "prim__addBigInt") Erased) (Constant $ BI 1)
@@ -517,44 +516,47 @@ irTerm top vs env (TType _) = return LNothing
517irTerm top vs env Erased = return LNothing
516irTerm top vs env Erased = return LNothing
518irTerm top vs env Impossible = return LNothing
517irTerm top vs env Impossible = return LNothing
520−getNatLikeCtors :: IState -> (S.Set Name, S.Set Name)
519+data LikeNat = LikeZ | LikeS
521−getNatLikeCtors ist =
520+
522− ( S.fromList $ map fst natLikeTypes
521+isLikeNat :: IState -> Name -> Maybe LikeNat
523− , S.fromList $ map snd natLikeTypes
522+isLikeNat ist cn
524− )
523+ | Just cTy <- lookupTyExact cn $ tt_ctxt ist
524+ , (P TCon{} tyN _, _) <- unApply $ getRetTy cTy
525+ , Just (z, s) <- natLikeCtors tyN cTy
526+ = if | cn == z -> Just LikeZ
527+ | cn == s -> Just LikeS
528+ | otherwise -> Nothing
530+ natLikeCtors :: Name -> Type -> Maybe (Name, Name)
531+ natLikeCtors tyN cTy = case lookupCtxtExact tyN $ idris_datatypes ist of
532+ Just TI{con_names = [z, s]}
533+ | 0 <- getUsedCount z
534+ , looksLikeS tyN s cTy
537+ Just TI{con_names = [s, z]}
538+ | 0 <- getUsedCount z
539+ , looksLikeS tyN s cTy
526 getUsedCount :: Name -> Int
544 getUsedCount :: Name -> Int
527 getUsedCount n =
545 getUsedCount n =
528 maybe 0 (length . usedpos)
546 maybe 0 (length . usedpos)
529 $ lookupCtxtExact n
547 $ lookupCtxtExact n
530 $ idris_callgraph ist
548 $ idris_callgraph ist
532− isRecursive :: Name -> Name -> Bool
550+ looksLikeS :: Name -> Name -> Type -> Bool
533− isRecursive tyN cn
551+ looksLikeS tyN cn cTy
534− | Just (Bind _ Pi{binderTy = P _ argTyN _} _) <- lookupTyExact cn $ tt_ctxt ist
552+ | Just [(i, _)] <- fmap usedpos $ lookupCtxtExact cn $ idris_callgraph ist
535− , argTyN == tyN
553+ , [recTy] <- [recTy | (j, (_n, recTy)) <- zip [0..] (getArgTys cTy), j == i]
554+ , (P TCon{} recTyN _, _) <- unApply recTy
538 | otherwise = False
558 | otherwise = False
540− natLikeTypes :: [(Name, Name)]
542− (typeName, TI{con_names}) <- toAlist $ idris_datatypes ist
545− | getUsedCount z == 0
546− , getUsedCount s == 1
547− , isRecursive typeName s
551− | getUsedCount z == 0
552− , getUsedCount s == 1
553− , isRecursive typeName s
556− _ -> [] -- not a 2-constructor family
558doForeign :: Vars -> [Name] -> [Term] -> Idris LExp
560doForeign :: Vars -> [Name] -> [Term] -> Idris LExp
559doForeign vs env (ret : fname : world : args)
561doForeign vs env (ret : fname : world : args)
560 = do args' <- mapM splitArg args
562 = do args' <- mapM splitArg args
@@ -690,10 +692,32 @@ irSC top vs ImpossibleCase = return LNothing
690irAlt :: Name -> Vars -> LExp -> CaseAlt -> Idris LAlt
692irAlt :: Name -> Vars -> LExp -> CaseAlt -> Idris LAlt
692-- this leaves out all unused arguments of the constructor
694-- this leaves out all unused arguments of the constructor
693−irAlt top vs _ (ConCase n t args sc) = do
695+irAlt top vs tm (ConCase n t args sc) = do
696+ likeNat <- isLikeNat <$> getIState <*> pure n
694 used <- map fst <$> fgetState (cg_usedpos . ist_callgraph n)
697 used <- map fst <$> fgetState (cg_usedpos . ist_callgraph n)
695 let usedArgs = [a | (i,a) <- zip [0..] args, i `elem` used]
698 let usedArgs = [a | (i,a) <- zip [0..] args, i `elem` used]
703+ sc' <- irSC top vs sc
705+ [pv] -> return $ LDefaultCase $ LLet pv
707+ (LMinus (ATInt ITBig))
714+ _ -> ifail $ "irAlt/LikeS: multiple used args: " ++ show usedArgs
717+ Just LikeZ -> LConstCase (BI 0) <$> irSC top vs sc
696− LConCase (-1) n usedArgs <$> irSC top (methodVars `M.union` vs) sc
720+ Nothing -> LConCase (-1) n usedArgs <$> irSC top (methodVars `M.union` vs) sc
698 methodVars = case n of
722 methodVars = case n of
699 SN (ImplementationCtorN interfaceName)
723 SN (ImplementationCtorN interfaceName)