@@ -15,7 +15,8 @@ import Idris.Core.TT
16import Control.Monad.State hiding (lift)
16import Control.Monad.State hiding (lift)
17import Data.Data (Data)
17import Data.Data (Data)
18−import Data.List
18+import Data.List
19+import qualified Data.Map.Strict as Map
19import Data.Typeable (Typeable)
20import Data.Typeable (Typeable)
20import GHC.Generics (Generic)
21import GHC.Generics (Generic)
@@ -44,26 +45,26 @@ data LExp = LV Name
44 | LOp PrimFn [LExp]
45 | LOp PrimFn [LExp]
45 | LNothing
46 | LNothing
46 | LError String
47 | LError String
47− deriving Eq
48+ deriving (Eq, Ord)
49data FDesc = FCon Name
50data FDesc = FCon Name
50 | FStr String
51 | FStr String
51 | FUnknown
52 | FUnknown
52 | FIO FDesc
53 | FIO FDesc
53 | FApp Name [FDesc]
54 | FApp Name [FDesc]
54− deriving (Show, Eq)
55+ deriving (Show, Eq, Ord)
56data Export = ExportData FDesc -- Exported data descriptor (usually string)
57data Export = ExportData FDesc -- Exported data descriptor (usually string)
57 | ExportFun Name -- Idris name
58 | ExportFun Name -- Idris name
58 FDesc -- Exported function descriptor
59 FDesc -- Exported function descriptor
59 FDesc -- Return type descriptor
60 FDesc -- Return type descriptor
60 [FDesc] -- Argument types
61 [FDesc] -- Argument types
61− deriving (Show, Eq)
62+ deriving (Show, Eq, Ord)
63data ExportIFace = Export Name -- FFI descriptor
64data ExportIFace = Export Name -- FFI descriptor
64 String -- interface file
65 String -- interface file
66− deriving (Show, Eq)
67+ deriving (Show, Eq, Ord)
68-- Primitive operators. Backends are not *required* to implement all
69-- Primitive operators. Backends are not *required* to implement all
69-- of these, but should report an error if they are unable
70-- of these, but should report an error if they are unable
@@ -96,12 +97,12 @@ data PrimFn = LPlus ArithTy | LMinus ArithTy | LTimes ArithTy
99− deriving (Show, Eq, Generic)
100+ deriving (Show, Eq, Ord, Generic)
101-- Supported target languages for foreign calls
102-- Supported target languages for foreign calls
103data FCallType = FStatic | FObject | FConstructor
104data FCallType = FStatic | FObject | FConstructor
104− deriving (Show, Eq)
105+ deriving (Show, Eq, Ord)
106data FType = FArith ArithTy
107data FType = FArith ArithTy
107 | FFunction
108 | FFunction
@@ -112,24 +113,24 @@ data FType = FArith ArithTy
112 | FManagedPtr
113 | FManagedPtr
115− deriving (Show, Eq)
116+ deriving (Show, Eq, Ord)
117-- FIXME: Why not use this for all the IRs now?
118-- FIXME: Why not use this for all the IRs now?
118data LAlt' e = LConCase Int Name [Name] e
119data LAlt' e = LConCase Int Name [Name] e
119 | LConstCase Const e
120 | LConstCase Const e
120 | LDefaultCase e
121 | LDefaultCase e
121− deriving (Show, Eq, Functor, Data, Typeable)
122+ deriving (Show, Eq, Ord, Functor, Data, Typeable)
123type LAlt = LAlt' LExp
124type LAlt = LAlt' LExp
125data LDecl = LFun [LOpt] Name [Name] LExp -- options, name, arg names, def
126data LDecl = LFun [LOpt] Name [Name] LExp -- options, name, arg names, def
126 | LConstructor Name Int Int -- constructor name, tag, arity
127 | LConstructor Name Int Int -- constructor name, tag, arity
127− deriving (Show, Eq)
128+ deriving (Show, Eq, Ord)
129type LDefs = Ctxt LDecl
130type LDefs = Ctxt LDecl
131data LOpt = Inline | NoInline
132data LOpt = Inline | NoInline
132− deriving (Show, Eq)
133+ deriving (Show, Eq, Ord)
134addTags :: Int -> [(Name, LDecl)] -> (Int, [(Name, LDecl)])
135addTags :: Int -> [(Name, LDecl)] -> (Int, [(Name, LDecl)])
135addTags i ds = tag i ds []
136addTags i ds = tag i ds []
@@ -140,37 +141,71 @@ addTags i ds = tag i ds []
140 tag i (x : as) acc = tag i as (x : acc)
141 tag i (x : as) acc = tag i as (x : acc)
141 tag i [] acc = (i, reverse acc)
142 tag i [] acc = (i, reverse acc)
143−data LiftState = LS Name Int [(Name, LDecl)]
144+data LiftState = LS (Maybe Name) Int [(Name, LDecl)]
145+ (Map.Map ([Name], LExp) Name) -- map from args/expressions
146+ -- to names, so we don't create the same function
149+setBaseName :: Name -> State LiftState ()
151+ = do LS _ i ds done <- get
152+ put (LS (Just n) i ds done)
145lname (NS n x) i = NS (lname n i) x
154lname (NS n x) i = NS (lname n i) x
146lname (UN n) i = MN i n
155lname (UN n) i = MN i n
147lname x i = sMN i (showCG x ++ "_lam")
156lname x i = sMN i (showCG x ++ "_lam")
149−liftAll :: [(Name, LDecl)] -> [(Name, LDecl)]
150−liftAll xs = concatMap (\ (x, d) -> lambdaLift x d) xs
152−lambdaLift :: Name -> LDecl -> [(Name, LDecl)]
153−lambdaLift n (LFun opts _ args e)
154− = let (e', (LS _ _ decls)) = runState (lift args e) (LS n 0 []) in
155− (n, LFun opts n args e') : decls
156−lambdaLift n x = [(n, x)]
158getNextName :: State LiftState Name
158getNextName :: State LiftState Name
159−getNextName = do LS n i ds <- get
159+getNextName
160+ = do LS mn i ds done <- get
161+ let newn = case mn of
162+ Nothing -> lname (sUN "_") i
160− put (LS n (i + 1) ds)
164+ put (LS mn (i + 1) ds done)
161− return (lname n i)
165+ return newn
167+renameArgs :: [Name] -> LExp -> ([Name], LExp)
169+ = let newargNames = map (\i -> sMN i "lift") [0..]
170+ newargs = zip args newargNames in
171+ (map snd newargs, rename newargs e)
163addFn :: Name -> LDecl -> State LiftState ()
173addFn :: Name -> LDecl -> State LiftState ()
164−addFn fn d = do LS n i ds <- get
174+addFn fn d
175+ = do LS n i ds done <- get
176+ put (LS n i ((fn, d) : ds) done)
178+makeFn :: [Name] -> LExp -> State LiftState Name
180+ = do fn <- getNextName
181+ let (args', exp') = renameArgs args exp
182+ LS n i ds done <- get
183+ case Map.lookup (args', exp') done of
184+ Just fn -> return fn
186+ do addFn fn (LFun [Inline] fn args' exp')
187+ LS n i ds done <- get
165− put (LS n i ((fn, d) : ds))
188+ put (LS n i ds (Map.insert (args', exp') fn done))
191+liftAll :: [(Name, LDecl)] -> [(Name, LDecl)]
193+ let (LS _ _ decls _) = execState (mapM_ liftDef xs) (LS Nothing 0 [] Map.empty) in
196+liftDef :: (Name, LDecl) -> State LiftState ()
197+liftDef (n, LFun opts _ args e) =
200+ addFn n (LFun opts n args e')
201+liftDef (n, x) = addFn n x
167lift :: [Name] -> LExp -> State LiftState LExp
203lift :: [Name] -> LExp -> State LiftState LExp
168lift env (LV v) = return (LV v) -- Lifting happens before these can exist...
204lift env (LV v) = return (LV v) -- Lifting happens before these can exist...
169lift env (LApp tc (LV n) args) = do args' <- mapM (lift env) args
205lift env (LApp tc (LV n) args) = do args' <- mapM (lift env) args
170 return (LApp tc (LV n) args')
206 return (LApp tc (LV n) args')
171lift env (LApp tc f args) = do f' <- lift env f
207lift env (LApp tc f args) = do f' <- lift env f
172− fn <- getNextName
208+ fn <- makeFn env f'
173− addFn fn (LFun [Inline] fn env f')
174 args' <- mapM (lift env) args
209 args' <- mapM (lift env) args
175 return (LApp tc (LV fn) (map LV env ++ args'))
210 return (LApp tc (LV fn) (map LV env ++ args'))
176lift env (LLazyApp n args) = do args' <- mapM (lift env) args
211lift env (LLazyApp n args) = do args' <- mapM (lift env) args
@@ -180,8 +215,7 @@ lift env (LLazyExp (LConst c)) = return (LConst c)
180-- = lift env (LLazyApp f args)
215-- = lift env (LLazyApp f args)
181lift env (LLazyExp e) = do e' <- lift env e
216lift env (LLazyExp e) = do e' <- lift env e
182 let usedArgs = nub $ usedIn env e'
217 let usedArgs = nub $ usedIn env e'
183− fn <- getNextName
218+ fn <- makeFn usedArgs e'
184− addFn fn (LFun [NoInline] fn usedArgs e')
185 return (LLazyApp fn (map LV usedArgs))
219 return (LLazyApp fn (map LV usedArgs))
186lift env (LForce e) = do e' <- lift env e
220lift env (LForce e) = do e' <- lift env e
187 return (LForce e')
221 return (LForce e')
@@ -190,8 +224,7 @@ lift env (LLet n v e) = do v' <- lift env v
190 return (LLet n v' e')
224 return (LLet n v' e')
191lift env (LLam args e) = do e' <- lift (env ++ args) e
225lift env (LLam args e) = do e' <- lift (env ++ args) e
192 let usedArgs = nub $ usedIn env e'
226 let usedArgs = nub $ usedIn env e'
194− addFn fn (LFun [Inline] fn (usedArgs ++ args) e')
227+ fn <- makeFn (usedArgs ++ args) e'
195 return (LApp False (LV fn) (map LV usedArgs))
228 return (LApp False (LV fn) (map LV usedArgs))
196lift env (LProj t i) = do t' <- lift env t
229lift env (LProj t i) = do t' <- lift env t
197 return (LProj t' i)
230 return (LProj t' i)
@@ -329,6 +362,35 @@ lsubst n new (LCase t e alts) = let e' = lsubst n new e
329 LCase t e' alts'
362 LCase t e' alts'
330lsubst n new tm = tm
363lsubst n new tm = tm
365+rename :: [(Name, Name)] -> LExp -> LExp
367+ = case lookup x ns of
370+rename ns (LApp t e args)
371+ = let e' = rename ns e
372+ args' = map (rename ns) args in
374+rename ns (LLazyApp fn args)
375+ = let args' = map (rename ns) args in
377+rename ns (LLazyExp e) = LLazyExp (rename ns e)
378+rename ns (LForce e) = LForce (rename ns e)
379+rename ns (LLet v val sc) = LLet v (rename ns val) (rename ns sc)
380+rename ns (LLam args sc) = LLam args (rename ns sc)
381+rename ns (LProj e i) = LProj (rename ns e) i
382+rename ns (LCon lv t cn args) = let args' = map (rename ns) args in
384+rename ns (LOp op args) = let args' = map (rename ns) args in
386+rename ns (LForeign fd rd args)
387+ = let args' = map (\(d, a) -> (d, rename ns a)) args in
388+ LForeign fd rd args'
389+rename ns (LCase t e alts) = let e' = rename ns e
390+ alts' = map (fmap (rename ns)) alts in
332instance Show LExp where
394instance Show LExp where
333 show e = show' [] "" e where
395 show e = show' [] "" e where
334 show' env ind (LV n) = show n
396 show' env ind (LV n) = show n
@@ -357,7 +419,7 @@ instance Show LExp where
357 atloc (Just l) = "@" ++ show (LV l) ++ ":"
419 atloc (Just l) = "@" ++ show (LV l) ++ ":"
359 show' env ind (LCase up e alts)
421 show' env ind (LCase up e alts)
360− = "case" ++ update ++ show' env ind e ++ " of \n" ++ fmt alts
422+ = "case" ++ update ++ "(" ++ show' env ind e ++ ") of \n" ++ fmt alts
362 update = case up of
424 update = case up of
363 Shared -> " "
425 Shared -> " "