3module IRTS.CodegenC where
15import System.Directory
16import System.Environment
19data DbgLevel = NONE | DEBUG | TRACE
21codegenC :: [(Name, SDecl)] ->
22 String -> -- output file name
23 Bool -> -- generate executable if True, only .o if False
24 [FilePath] -> -- include files
25 String -> -- extra compiler flags
28codegenC defs out exec incs libs dbg
30 let bc = map toBC defs
31 let h = concatMap toDecl (map fst bc)
32 let cc = concatMap (uncurry toC) bc
34 mprog <- readFile (d ++ "/rts/idris_main.c")
35 let cout = headers incs ++ debug dbg ++ h ++ cc ++
36 (if exec then mprog else "")
37 (tmpn, tmph) <- tempfile
41 let gcc = "gcc -x c " ++
42 (if exec then "" else " - c ") ++
45 " `idris --link` `idris --include` " ++ libs ++
46 " -lidris_rts -o " ++ out
49 when (exit /= ExitSuccess) $
50 putStrLn ("FAILURE: " ++ gcc)
52headers [] = "#include <idris_rts.h>\n\n"
53headers (x : xs) = "#include <" ++ x ++ ">\n" ++ headers xs
55debug TRACE = "#define IDRIS_DEBUG\n\n"
62cname :: Name -> String
63cname n = "_idris_" ++ concatMap cchar (show n)
64 where cchar x | isAlpha x || isDigit x = [x]
65 | otherwise = "_" ++ show (fromEnum x) ++ "_"
67indent i = take (i * 4) (repeat ' ')
70creg (L i) = "LOC(" ++ show i ++ ")"
71creg (T i) = "TOP(" ++ show i ++ ")"
73toDecl :: Name -> String
74toDecl f = "void " ++ cname f ++ "(VM*, VAL*);\n"
76toC :: Name -> [BC] -> String
78 = -- "/* " ++ show code ++ "*/\n\n" ++
79 "void " ++ cname f ++ "(VM* vm, VAL* oldbase) {\n" ++
80 indent 1 ++ "INITFRAME;\n" ++
81 concatMap (bcc 1) code ++ "}\n\n"
83bcc :: Int -> BC -> String
84bcc i (ASSIGN l r) = indent i ++ creg l ++ " = " ++ creg r ++ ";\n"
85bcc i (ASSIGNCONST l c)
86 = indent i ++ creg l ++ " = " ++ mkConst c ++ ";\n"
88 mkConst (I i) = "MKINT(" ++ show i ++ ")"
89 mkConst (BI i) = "MKINT(" ++ show i ++ ")" -- TODO
90 mkConst (Fl f) = "MKFLOAT(vm, " ++ show f ++ ")"
91 mkConst (Ch c) = "MKINT(" ++ show (fromEnum c) ++ ")"
92 mkConst (Str s) = "MKSTR(vm, " ++ show s ++ ")"
93 mkConst _ = "MKINT(42424242)"
94bcc i (MKCON l tag args)
95 = indent i ++ creg l ++ " = MKCON(vm, " ++ show tag ++ ", " ++
96 show (length args) ++ concatMap showArg args ++ ");\n"
97 where showArg r = ", " ++ creg r
98bcc i (PROJECT l loc a) = indent i ++ "PROJECT(vm, " ++ creg l ++ ", " ++ show loc ++
99 ", " ++ show a ++ ");\n"
100bcc i (CASE r code def)
101 = indent i ++ "switch(TAG(" ++ creg r ++ ")) {\n" ++
102 concatMap (showCase i) code ++
106 showCase i (t, bc) = indent i ++ "case " ++ show t ++ ":\n"
107 ++ concatMap (bcc (i+1)) bc ++ indent (i + 1) ++ "break;\n"
108 showDef i Nothing = ""
109 showDef i (Just c) = indent i ++ "default:\n"
110 ++ concatMap (bcc (i+1)) c ++ indent (i + 1) ++ "break;\n"
111bcc i (CONSTCASE r code def)
112 = indent i ++ "switch(GETINT(" ++ creg r ++ ")) {\n" ++
113 concatMap (showCase i) code ++
117 showCase i (t, bc) = indent i ++ "case " ++ show t ++ ":\n"
118 ++ concatMap (bcc (i+1)) bc ++ indent (i + 1) ++ "break;\n"
119 showDef i Nothing = ""
120 showDef i (Just c) = indent i ++ "default:\n"
121 ++ concatMap (bcc (i+1)) c ++ indent (i + 1) ++ "break;\n"
122bcc i (CALL n) = indent i ++ "CALL(" ++ cname n ++ ");\n"
123bcc i (TAILCALL n) = indent i ++ "TAILCALL(" ++ cname n ++ ");\n"
124bcc i (SLIDE n) = indent i ++ "SLIDE(vm, " ++ show n ++ ");\n"
125bcc i REBASE = indent i ++ "REBASE;\n"
126bcc i (RESERVE n) = indent i ++ "RESERVE(" ++ show n ++ ");\n"
127bcc i (ADDTOP n) = indent i ++ "ADDTOP(" ++ show n ++ ");\n"
128bcc i (TOPBASE n) = indent i ++ "TOPBASE(" ++ show n ++ ");\n"
129bcc i (BASETOP n) = indent i ++ "BASETOP(" ++ show n ++ ");\n"
130bcc i STOREOLD = indent i ++ "STOREOLD;\n"
131bcc i (OP l fn args) = indent i ++ creg l ++ " = " ++ doOp fn args ++ ";\n"
132bcc i (FOREIGNCALL l LANG_C rty fn args)
133 = indent i ++ creg l ++ " = " ++
134 c_irts rty (fn ++ "(" ++ showSep "," (map fcall args) ++ ")") ++ ";\n"
135 where fcall (t, arg) = irts_c t (creg arg)
136-- bcc i _ = indent i ++ "// not done yet\n"
138c_irts FInt x = "MKINT((i_int)(" ++ x ++ ")"
139c_irts FString x = "MKSTR(" ++ x ++ ")"
140c_irts FUnit x = "MKINT(42424242)"
141c_irts FPtr x = "MKPTR(" ++ x ++ ")"
142c_irts FDouble x = "MKFLOAT(vm, " ++ x ++ ")"
145irts_c FInt x = "GETINT(" ++ x ++ ")"
146irts_c FString x = "GETSTR(" ++ x ++ ")"
148irts_c FPtr x = "GETPTR(" ++ x ++ ")"
149irts_c FDouble x = "GETFLOAT(" ++ x ++ ")"
152doOp LPlus [l, r] = "ADD(" ++ creg l ++ ", " ++ creg r ++ ")"
153doOp LMinus [l, r] = "INTOP(-," ++ creg l ++ ", " ++ creg r ++ ")"
154doOp LTimes [l, r] = "MULT(" ++ creg l ++ ", " ++ creg r ++ ")"
155doOp LDiv [l, r] = "INTOP(/," ++ creg l ++ ", " ++ creg r ++ ")"
156doOp LEq [l, r] = "INTOP(==," ++ creg l ++ ", " ++ creg r ++ ")"
157doOp LLt [l, r] = "INTOP(<," ++ creg l ++ ", " ++ creg r ++ ")"
158doOp LLe [l, r] = "INTOP(<=," ++ creg l ++ ", " ++ creg r ++ ")"
159doOp LGt [l, r] = "INTOP(>," ++ creg l ++ ", " ++ creg r ++ ")"
160doOp LGe [l, r] = "INTOP(>=," ++ creg l ++ ", " ++ creg r ++ ")"
162doOp LFPlus [l, r] = "FLOATOP(+" ++ creg l ++ ", " ++ creg r ++ ")"
163doOp LFMinus [l, r] = "FLOATOP(-," ++ creg l ++ ", " ++ creg r ++ ")"
164doOp LFTimes [l, r] = "FLOATOP(*" ++ creg l ++ ", " ++ creg r ++ ")"
165doOp LFDiv [l, r] = "FLOATOP(/," ++ creg l ++ ", " ++ creg r ++ ")"
166doOp LFEq [l, r] = "FLOATBOP(==," ++ creg l ++ ", " ++ creg r ++ ")"
167doOp LFLt [l, r] = "FLOATBOP(<," ++ creg l ++ ", " ++ creg r ++ ")"
168doOp LFLe [l, r] = "FLOATBOP(<=," ++ creg l ++ ", " ++ creg r ++ ")"
169doOp LFGt [l, r] = "FLOATBOP(>," ++ creg l ++ ", " ++ creg r ++ ")"
170doOp LFGe [l, r] = "FLOATBOP(>=," ++ creg l ++ ", " ++ creg r ++ ")"
172doOp LStrConcat [l,r] = "idris_concat(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
173doOp LStrLt [l,r] = "idris_strlt(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
174doOp LStrEq [l,r] = "idris_streq(vm, " ++ creg l ++ ", " ++ creg r ++ ")"
175doOp LStrLen [x] = "idris_strlen(vm, " ++ creg x ++ ")"
177doOp LIntFloat [x] = "idris_castIntFloat(" ++ creg x ++ ")"
178doOp LFloatInt [x] = "idris_castFloatInt(" ++ creg x ++ ")"
179doOp LIntStr [x] = "idris_castIntStr(vm, " ++ creg x ++ ")"
180doOp LStrInt [x] = "idris_castFloatStr(vm, " ++ creg x ++ ")"
181doOp LFloatStr [x] = "idris_castFloatStr(vm, " ++ creg x ++ ")"
182doOp LStrFloat [x] = "idris_castStrFloat(vm, " ++ creg x ++ ")"
184doOp LReadStr [] = "idris_readStr(vm, stdin)"
185doOp LPrintNum [x] = creg x ++ "; printf(\"%ld\\n\", GETINT(" ++ creg x ++ "))"
186doOp LPrintStr [x] = creg x ++ "; puts(GETSTR(" ++ creg x ++ "))"
189tempfile :: IO (FilePath, Handle)
190tempfile = do env <- environment "TMPDIR"
191 let dir = case env of
194 openTempFile dir "idris"
196environment :: String -> IO (Maybe String)
197environment x = catch (do e <- getEnv x
199#if MIN_VERSION_base(4,6,0)
200 (\y-> do return (y::SomeException); return Nothing)
202#if !MIN_VERSION_base(4,6,0)
203 (\_-> return Nothing)
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