1{-# LANGUAGE PatternGuards #-}
3module IRTS.Compiler where
6import IRTS.Defunctionalise
13import Idris.UnusedArgs
19import Control.Monad.State
23import System.Directory
24import System.Environment
28compile :: Target -> FilePath -> Term -> Idris ()
31 let tmnames = namesUsed (STerm tm)
32 used <- mapM (allNames []) tmnames
33 defsIn <- mkDecls tm (concat used)
34 findUnusedArgs (concat used)
36 objs <- getObjectFiles
39 let defs = defsIn ++ [(MN 0 "runMain", maindef)]
40 -- iputStrLn $ showSep "\n" (map show defs)
41 let (nexttag, tagged) = addTags 65536 (liftAll defs)
42 let ctxtIn = addAlist tagged emptyContext
43 iLOG "Defunctionalising"
44 let defuns_in = defunctionalise nexttag ctxtIn
45 logLvl 5 $ show defuns_in
47 let defuns = inline defuns_in
48 logLvl 5 $ show defuns
49 iLOG "Resolving variables for CG"
50 -- iputStrLn $ showSep "\n" (map show (toAlist defuns))
51 let checked = checkDefs defuns (toAlist defuns)
53 dumpCases <- getDumpCases
54 dumpDefun <- getDumpDefun
57 Just f -> liftIO $ writeFile f (showCaseTrees tagged)
60 Just f -> liftIO $ writeFile f (dumpDefuns defuns)
61 iLOG "Building output"
63 OK c -> case target of
64 ViaC -> liftIO $ codegenC dumpC c f True hdrs
65 (concatMap mkObj objs)
66 (concatMap mkLib libs) NONE
67 ViaJava -> liftIO $ codegenJava c f
68 Error e -> fail $ show e
69 where checkMVs = do i <- get
70 case idris_metavars i \\ primDefs of
72 ms -> fail $ "There are undefined metavariables: " ++ show ms
73 inDir d h = do let f = d ++ "/" ++ h
75 if ex then return f else return h
77 mkLib l = "-l" ++ l ++ " "
81irMain :: TT Name -> Idris LDecl
82irMain tm = do i <- ir tm
83 return $ LFun (MN 0 "runMain") [] (LForce i)
85allNames :: [Name] -> Name -> Idris [Name]
86allNames ns n | n `elem` ns = return []
87allNames ns n = do i <- get
88 case lookupCtxt Nothing n (idris_callgraph i) of
89 [ns'] -> do more <- mapM (allNames (n:ns)) (map fst (calls ns'))
90 return (nub (n : concat more))
93mkDecls :: Term -> [Name] -> Idris [(Name, LDecl)]
96 let ds = filter (\ (n, d) -> n `elem` used || isCon d) $ ctxtAlist (tt_ctxt i)
98 decls <- mapM build ds
101showCaseTrees :: [(Name, LDecl)] -> String
102showCaseTrees ds = showSep "\n\n" (map showCT ds)
104 showCT (n, LFun f args lexp)
105 = show n ++ " " ++ showSep " " (map show args) ++ " =\n\t "
107 showCT (n, LConstructor c t a) = "data " ++ show n ++ " " ++ show a
109isCon (TyDecl _ _) = True
113 ir :: a -> Idris LExp
115build :: (Name, Def) -> Idris (Name, LDecl)
118 case lookup n (idris_scprims i) of
120 let args = map (\x -> MN x "op") [0..] in
121 return (n, (LFun n (take ar args)
122 (LOp op (map (LV . Glob) (take ar args)))))
123 _ -> do def <- mkLDecl n d
124 logLvl 3 $ "Compiled " ++ show n ++ " =\n\t" ++ show def
127declArgs args n (LLam xs x) = declArgs (args ++ xs) n x
128declArgs args n x = LFun n args x
130mkLDecl n (Function tm _) = do e <- ir tm
131 return (declArgs [] n e)
132mkLDecl n (CaseOp _ _ _ _ pats _ _ args sc) = do e <- ir (args, sc)
133 return (declArgs [] n e)
134mkLDecl n (TyDecl (DCon t a) _) = return $ LConstructor n t a
135mkLDecl n (TyDecl (TCon t a) _) = return $ LConstructor n (-1) a
136mkLDecl n _ = return (LFun n [] (LError ("Impossible declaration " ++ show n)))
138instance ToIR (TT Name) where
139 ir tm = ir' [] tm where
141 | (P _ (UN "mkForeign") _, args) <- unApply tm
143 | (P _ (UN "unsafePerformIO") _, [_, arg]) <- unApply tm
145 | (P _ (UN "lazy") _, [_, arg]) <- unApply tm
146 = do arg' <- ir' env arg
147 return $ LLazyExp arg'
148 | (P _ (UN "par") _, [_, arg]) <- unApply tm
149 = do arg' <- ir' env arg
150 return $ LOp LPar [LLazyExp arg']
151 | (P _ (UN "fork") _, [arg]) <- unApply tm
152 = do arg' <- ir' env arg
153 return $ LOp LFork [LLazyExp arg']
154 | (P _ (UN "prim__IO") _, [v]) <- unApply tm
157 | (P _ (UN "io_bind") _, [_,_,v,k]) <- unApply tm
160 return (LApp False k' [LForce v'])
161 | (P _ (UN "malloc") _, [_,size,t]) <- unApply tm
162 = do size' <- ir' env size
164 return t' -- TODO $ malloc_ size' t'
165 | (P _ (UN "trace_malloc") _, [_,t]) <- unApply tm
168 | (P (DCon t a) n _, args) <- unApply tm
169 = irCon env t a n args
170 | (P _ n _, args) <- unApply tm
172 let collapse = case lookupCtxt Nothing n (idris_optimisation i) of
173 [oi] -> collapsible oi
175 let unused = case lookupCtxt Nothing n (idris_callgraph i) of
176 [CGInfo _ _ _ _ unusedpos] -> unusedpos
178 args' <- mapM (ir' env) args
179 if collapse then return LNothing
180 else return (LApp False (LV (Glob n))
181 (mkUnused unused 0 args'))
182 | (f, args) <- unApply tm
184 args' <- mapM (ir' env) args
185 return (LApp False f' args')
186 where mkUnused u i [] = []
187 mkUnused u i (x : xs) | i `elem` u = LNothing : mkUnused u (i + 1) xs
188 | otherwise = x : mkUnused u (i + 1) xs
189 ir' env (P _ n _) = return $ LV (Glob n)
190 ir' env (V i) | i < length env = return $ LV (Glob (env!!i))
191 | otherwise = error $ "IR fail " ++ show i ++ " " ++ show tm
192 ir' env (Bind n (Lam _) sc)
193 = do let n' = uniqueName n env
194 sc' <- ir' (n' : env) sc
195 return $ LLam [n'] sc'
196 ir' env (Bind n (Let _ v) sc)
197 = do sc' <- ir' (n : env) sc
199 return $ LLet n v' sc'
200 ir' env (Bind _ _ _) = return $ LNothing
201 ir' env (Proj t i) = do t' <- ir' env t
203 ir' env (Constant c) = return $ LConst c
204 ir' env (Set _) = return $ LNothing
205 ir' env Erased = return $ LNothing
206 ir' env Impossible = return $ LNothing
207-- ir' env _ = return $ LError "Impossible"
209 irCon env t arity n args
210 | length args == arity = buildApp env (LV (Glob n)) args
211 | otherwise = let extra = satArgs (arity - length args) in
212 do sc' <- irCon env t arity n
213 (args ++ map (\n -> P Bound n undefined) extra)
214 return $ LLam extra sc'
216 satArgs n = map (\i -> MN i "sat") [1..n]
218 buildApp env e [] = return e
219 buildApp env e xs = do xs' <- mapM (ir' env) xs
220 return $ LApp False e xs'
222 doForeign :: [Name] -> [TT Name] -> Idris LExp
223 doForeign env (_ : fgn : args)
224 | (_, (Constant (Str fgnName) : fgnArgTys : ret : [])) <- unApply fgn
225 = let tys = getFTypes fgnArgTys
227 do args' <- mapM (ir' env) args
228 -- wrap it in a prim__IO
229 -- return $ con_ 0 @@ impossible @@
231 LForeign LANG_C rty fgnName (zip tys args')
232 | otherwise = fail "Badly formed foreign function call"
234getFTypes :: TT Name -> [FType]
235getFTypes tm = case unApply tm of
238 let rest = getFTypes xs in
241mkIty' (P _ (UN ty) _) = mkIty ty
245mkIty "FFloat" = FDouble
247mkIty "FString" = FString
251instance ToIR ([Name], SC) where
252 ir (args, tree) = do logLvl 3 $ "Compiling " ++ show args ++ "\n" ++ show tree
254 return $ LLam args tree'
256instance ToIR SC where
260 ir' (UnmatchedCase str) = return $ LError str
261 ir' (ProjCase tm alts) = do alts' <- mapM mkIRAlt alts
263 return $ LCase tm' alts'
264 ir' (Case n alts) = do alts' <- mapM mkIRAlt alts
265 return $ LCase (LV (Glob n)) alts'
266 ir' ImpossibleCase = return LNothing
268 mkIRAlt (ConCase n t args rhs)
270 return $ LConCase (-1) n args rhs'
271 mkIRAlt (ConstCase (I i) rhs)
273 return $ LConstCase (I i) rhs'
274 mkIRAlt (ConstCase IType rhs)
276 return $ LDefaultCase rhs'
277 mkIRAlt (ConstCase c rhs)
278 = fail $ "Can only pattern match on integer constants (" ++ show c ++ ")"
279 mkIRAlt (DefaultCase rhs)
281 return $ LDefaultCase rhs'
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list