1{-# LANGUAGE PatternGuards #-}
3module IRTS.Compiler where
6import IRTS.Defunctionalise
8import IRTS.CodegenCommon
10import IRTS.CodegenJava
15import Idris.UnusedArgs
21import Control.Monad.State
25import System.Directory
26import System.Environment
27import System.FilePath ((</>), addTrailingPathSeparator)
31compile :: Target -> FilePath -> Term -> Idris ()
34 let tmnames = namesUsed (STerm tm)
35 usedIn <- mapM (allNames []) tmnames
36 let used = [UN "prim__subBigInt", UN "prim__addBigInt"] : usedIn
37 defsIn <- mkDecls tm (concat used)
38 findUnusedArgs (concat used)
40 objs <- getObjectFiles
43 let defs = defsIn ++ [(MN 0 "runMain", maindef)]
44 -- iputStrLn $ showSep "\n" (map show defs)
45 let (nexttag, tagged) = addTags 65536 (liftAll defs)
46 let ctxtIn = addAlist tagged emptyContext
47 iLOG "Defunctionalising"
48 let defuns_in = defunctionalise nexttag ctxtIn
49 logLvl 5 $ show defuns_in
51 let defuns = inline defuns_in
52 logLvl 5 $ show defuns
53 iLOG "Resolving variables for CG"
54 -- iputStrLn $ showSep "\n" (map show (toAlist defuns))
55 let checked = checkDefs defuns (toAlist defuns)
57 dumpCases <- getDumpCases
58 dumpDefun <- getDumpDefun
61 Just f -> liftIO $ writeFile f (showCaseTrees tagged)
64 Just f -> liftIO $ writeFile f (dumpDefuns defuns)
65 iLOG "Building output"
67 OK c -> case target of
68 ViaC -> liftIO $ codegenC c f outty hdrs
69 (concatMap mkObj objs)
70 (concatMap mkLib libs) NONE
71 ViaJava -> liftIO $ codegenJava c f outty
72 Bytecode -> liftIO $ dumpBC c f
73 Error e -> fail $ show e
74 where checkMVs = do i <- get
75 case idris_metavars i \\ primDefs of
77 ms -> fail $ "There are undefined metavariables: " ++ show ms
78 inDir d h = do let f = d </> h
80 if ex then return f else return h
82 mkLib l = "-l" ++ l ++ " "
86irMain :: TT Name -> Idris LDecl
87irMain tm = do i <- ir tm
88 return $ LFun (MN 0 "runMain") [] (LForce i)
90allNames :: [Name] -> Name -> Idris [Name]
91allNames ns n | n `elem` ns = return []
92allNames ns n = do i <- get
93 case lookupCtxt Nothing n (idris_callgraph i) of
94 [ns'] -> do more <- mapM (allNames (n:ns)) (map fst (calls ns'))
95 return (nub (n : concat more))
98mkDecls :: Term -> [Name] -> Idris [(Name, LDecl)]
101 let ds = filter (\ (n, d) -> n `elem` used || isCon d) $ ctxtAlist (tt_ctxt i)
102 mapM traceUnused used
103 decls <- mapM build ds
106showCaseTrees :: [(Name, LDecl)] -> String
107showCaseTrees ds = showSep "\n\n" (map showCT ds)
109 showCT (n, LFun f args lexp)
110 = show n ++ " " ++ showSep " " (map show args) ++ " =\n\t "
112 showCT (n, LConstructor c t a) = "data " ++ show n ++ " " ++ show a
114isCon (TyDecl _ _) = True
118 ir :: a -> Idris LExp
120build :: (Name, Def) -> Idris (Name, LDecl)
123 case lookup n (idris_scprims i) of
125 let args = map (\x -> MN x "op") [0..] in
126 return (n, (LFun n (take ar args)
127 (LOp op (map (LV . Glob) (take ar args)))))
128 _ -> do def <- mkLDecl n d
129 logLvl 3 $ "Compiled " ++ show n ++ " =\n\t" ++ show def
132declArgs args n (LLam xs x) = declArgs (args ++ xs) n x
133declArgs args n x = LFun n args x
135mkLDecl n (Function tm _) = do e <- ir tm
136 return (declArgs [] n e)
137mkLDecl n (CaseOp _ _ _ _ pats _ _ args sc) = do e <- ir (args, sc)
138 return (declArgs [] n e)
139mkLDecl n (TyDecl (DCon t a) _) = return $ LConstructor n t a
140mkLDecl n (TyDecl (TCon t a) _) = return $ LConstructor n (-1) a
141mkLDecl n _ = return (LFun n [] (LError ("Impossible declaration " ++ show n)))
143instance ToIR (TT Name) where
144 ir tm = ir' [] tm where
146 | (P _ (UN "mkForeign") _, args) <- unApply tm
148 | (P _ (UN "unsafePerformIO") _, [_, arg]) <- unApply tm
150 -- TMP HACK - until we get inlining.
151 | (P _ (UN "replace") _, [_, _, _, _, _, arg]) <- unApply tm
153 | (P _ (UN "lazy") _, [_, arg]) <- unApply tm
154 = do arg' <- ir' env arg
155 return $ LLazyExp arg'
156 | (P _ (UN "par") _, [_, arg]) <- unApply tm
157 = do arg' <- ir' env arg
158 return $ LOp LPar [LLazyExp arg']
159 | (P _ (UN "fork") _, [arg]) <- unApply tm
160 = do arg' <- ir' env arg
161 return $ LOp LFork [LLazyExp arg']
162 | (P _ (UN "prim__IO") _, [v]) <- unApply tm
165 | (P _ (UN "io_bind") _, [_,_,v,k]) <- unApply tm
168 return (LApp False k' [LForce v'])
169 | (P _ (UN "malloc") _, [_,size,t]) <- unApply tm
170 = do size' <- ir' env size
172 return t' -- TODO $ malloc_ size' t'
173 | (P _ (UN "trace_malloc") _, [_,t]) <- unApply tm
176-- | (P _ (NS (UN "S") ["Nat", "Prelude"]) _, [k]) <- unApply tm
177-- = do k' <- ir' env k
178-- return (LOp LBPlus [k', LConst (BI 1)])
179 | (P (DCon t a) n _, args) <- unApply tm
180 = irCon env t a n args
181 | (P _ n _, args) <- unApply tm
183 let collapse = case lookupCtxt Nothing n (idris_optimisation i) of
184 [oi] -> collapsible oi
186 let unused = case lookupCtxt Nothing n (idris_callgraph i) of
187 [CGInfo _ _ _ _ unusedpos] -> unusedpos
189 args' <- mapM (ir' env) args
190 if collapse then return LNothing
191 else return (LApp False (LV (Glob n))
192 (mkUnused unused 0 args'))
193 | (f, args) <- unApply tm
195 args' <- mapM (ir' env) args
196 return (LApp False f' args')
197 where mkUnused u i [] = []
198 mkUnused u i (x : xs) | i `elem` u = LNothing : mkUnused u (i + 1) xs
199 | otherwise = x : mkUnused u (i + 1) xs
200-- ir' env (P _ (NS (UN "O") ["Nat", "Prelude"]) _)
201-- = return $ LConst (BI 0)
202 ir' env (P _ n _) = return $ LV (Glob n)
203 ir' env (V i) | i < length env = return $ LV (Glob (env!!i))
204 | otherwise = error $ "IR fail " ++ show i ++ " " ++ show tm
205 ir' env (Bind n (Lam _) sc)
206 = do let n' = uniqueName n env
207 sc' <- ir' (n' : env) sc
208 return $ LLam [n'] sc'
209 ir' env (Bind n (Let _ v) sc)
210 = do sc' <- ir' (n : env) sc
212 return $ LLet n v' sc'
213 ir' env (Bind _ _ _) = return $ LNothing
214 ir' env (Proj t i) = do t' <- ir' env t
216 ir' env (Constant c) = return $ LConst c
217 ir' env (Set _) = return $ LNothing
218 ir' env Erased = return $ LNothing
219 ir' env Impossible = return $ LNothing
220-- ir' env _ = return $ LError "Impossible"
222 irCon env t arity n args
223 | length args == arity = buildApp env (LV (Glob n)) args
224 | otherwise = let extra = satArgs (arity - length args) in
225 do sc' <- irCon env t arity n
226 (args ++ map (\n -> P Bound n undefined) extra)
227 return $ LLam extra sc'
229 satArgs n = map (\i -> MN i "sat") [1..n]
231 buildApp env e [] = return e
232 buildApp env e xs = do xs' <- mapM (ir' env) xs
233 return $ LApp False e xs'
235 doForeign :: [Name] -> [TT Name] -> Idris LExp
236 doForeign env (_ : fgn : args)
237 | (_, (Constant (Str fgnName) : fgnArgTys : ret : [])) <- unApply fgn
238 = let tys = getFTypes fgnArgTys
240 do args' <- mapM (ir' env) args
241 -- wrap it in a prim__IO
242 -- return $ con_ 0 @@ impossible @@
244 LForeign LANG_C rty fgnName (zip tys args')
245 | otherwise = fail "Badly formed foreign function call"
247getFTypes :: TT Name -> [FType]
248getFTypes tm = case unApply tm of
251 let rest = getFTypes xs in
254mkIty' (P _ (UN ty) _) = mkIty ty
258mkIty "FFloat" = FDouble
260mkIty "FString" = FString
264zname = NS (UN "O") ["Nat","Prelude"]
265sname = NS (UN "S") ["Nat","Prelude"]
267instance ToIR ([Name], SC) where
268 ir (args, tree) = do logLvl 3 $ "Compiling " ++ show args ++ "\n" ++ show tree
270 return $ LLam args tree'
272instance ToIR SC where
276 ir' (UnmatchedCase str) = return $ LError str
277 ir' (ProjCase tm alts) = do alts' <- mapM (mkIRAlt tm) alts
279 return $ LCase tm' alts'
280 ir' (Case n alts) = do alts' <- mapM (mkIRAlt (P Bound n Erased)) alts
281 return $ LCase (LV (Glob n)) alts'
282 ir' ImpossibleCase = return LNothing
284 -- special cases for O and S
285 -- Needs rethink: projections make this fail
286-- mkIRAlt n (ConCase z _ [] rhs) | z == zname
287-- = mkIRAlt n (ConstCase (BI 0) rhs)
288-- mkIRAlt n (ConCase s _ [arg] rhs) | s == sname
291-- return $ LDefaultCase
292-- (LLet arg (LOp LBMinus [n', LConst (BI 1)])
294 mkIRAlt _ (ConCase n t args rhs)
296 return $ LConCase (-1) n args rhs'
297 mkIRAlt _ (ConstCase x rhs)
300 return $ LConstCase x rhs'
303 return $ LDefaultCase rhs'
304 mkIRAlt _ (ConstCase c rhs)
305 = fail $ "Can't match on (" ++ show c ++ ")"
306 mkIRAlt _ (DefaultCase rhs)
308 return $ LDefaultCase rhs'
310 matchable (I _) = True
311 matchable (BI _) = True
312 matchable (Ch _) = True
313 matchable (Str _) = True
316 matchableTy IType = True
317 matchableTy BIType = True
318 matchableTy ChType = True
319 matchableTy StrType = True
321 matchableTy W8Type = True
322 matchableTy W16Type = True
324 matchableTy _ = False
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