@@ -1,11 +1,67 @@
1module IRTS.CodegenC where
3module IRTS.CodegenC where
3import IRTS.Bytecode
5import IRTS.Bytecode
4import IRTS.Lang
6import IRTS.Lang
5import Core.TT
8import Core.TT
6import Paths_idris
9import Paths_idris
8import Data.Char
11import Data.Char
15+import System.Directory
16+import System.Environment
19+data DbgLevel = NONE | DEBUG | TRACE
21+codegenC :: [(Name, LDecl)] ->
22+ String -> -- output file name
23+ Bool -> -- generate executable if True, only .o if False
24+ [FilePath] -> -- include files
25+ String -> -- extra compiler flags
28+codegenC defs out exec incs libs dbg
29+ = do let tagged = addTags defs
30+ let ctxtIn = addAlist tagged emptyContext
31+ let checked = checkDefs ctxtIn tagged
33+ OK c -> do let bc = map toBC c
34+ let h = concatMap toDecl (map fst bc)
35+ let cc = concatMap (uncurry toC) bc
37+ mprog <- readFile (d ++ "/rts/idris_main.c")
38+ let cout = headers incs ++ debug dbg ++ h ++ cc ++
39+ (if exec then mprog else "")
40+ (tmpn, tmph) <- tempfile
44+ let gcc = "gcc -x c " ++
45+ (if exec then "" else " - c ") ++
48+ " `idris --link` `idris --include` " ++ libs ++
49+ " -lidris_rts -o " ++ out
51+ when (exit /= ExitSuccess) $
52+ putStrLn ("FAILURE: " ++ gcc)
54+ Error e -> fail $ "Can't happen: Something went wrong in codegenC\n" ++ show e
56+headers [] = "#include <idris_rts.h>\n\n"
57+headers (x : xs) = "#include <" ++ x ++ ">\n" ++ headers xs
59+debug DEBUG = "#define IDRIS_DEBUG\n\n"
10cname :: Name -> String
66cname :: Name -> String
11cname n = "_idris_" ++ concatMap cchar (show n)
67cname n = "_idris_" ++ concatMap cchar (show n)
@@ -77,6 +133,10 @@ bcc i (TOPBASE n) = indent i ++ "TOPBASE(" ++ show n ++ ");\n"
77bcc i (BASETOP n) = indent i ++ "BASETOP(" ++ show n ++ ");\n"
133bcc i (BASETOP n) = indent i ++ "BASETOP(" ++ show n ++ ");\n"
78bcc i STOREOLD = indent i ++ "STOREOLD;\n"
134bcc i STOREOLD = indent i ++ "STOREOLD;\n"
79bcc i (OP l fn args) = indent i ++ creg l ++ " = " ++ doOp fn args ++ ";\n"
135bcc i (OP l fn args) = indent i ++ creg l ++ " = " ++ doOp fn args ++ ";\n"
136+bcc i (FOREIGNCALL l LANG_C rty fn args)
137+ = indent i ++ creg l ++ " = " ++
138+ c_irts rty (fn ++ "(" ++ showSep "," (map fcall args) ++ ")") ++ ";\n"
139+ where fcall (t, arg) = irts_c t (creg l)
80-- bcc i _ = indent i ++ "// not done yet\n"
140-- bcc i _ = indent i ++ "// not done yet\n"
82c_irts FInt x = "MKINT((i_int)(" ++ x ++ ")"
142c_irts FInt x = "MKINT((i_int)(" ++ x ++ ")"
@@ -130,3 +190,19 @@ doOp LPrintNum [x] = "NULL; printf(\"%ld\\n\", GETINT(" ++ creg x ++ "))"
130doOp LPrintStr [x] = "NULL; puts(GETSTR(" ++ creg x ++ "))"
190doOp LPrintStr [x] = "NULL; puts(GETSTR(" ++ creg x ++ "))"
131doOp _ _ = "FAIL"
191doOp _ _ = "FAIL"
193+tempfile :: IO (FilePath, Handle)
194+tempfile = do env <- environment "TMPDIR"
195+ let dir = case env of
198+ openTempFile dir "idris"
200+environment :: String -> IO (Maybe String)
201+environment x = catch (do e <- getEnv x
203+#if MIN_VERSION_base(4,6,0)
204+ (\y-> do return (y::SomeException); return Nothing)
206+#if !MIN_VERSION_base(4,6,0)
207+ (\_-> return Nothing)