1module RTS.CodegenC where
15import Control.Monad.State
18import System.Directory
19import System.Environment
20import System.FilePath ((</>))
25compileC :: FilePath -> Term -> Idris ()
28 let tmnames = namesUsed (STerm tm)
29 used <- mapM (allNames []) tmnames
31 let entry = mainFn (idris_scprims i) tm
32 scs' <- mkDecls tm (concat used)
33 let scs = scs' ++ entry
34 objs <- getObjectFiles
37 ddir <- liftIO $ getDataDir
38 -- if any includes exist in the data directory, use that
39 hdrs' <- liftIO $ mapM (inDir ddir) hdrs
41 let pcs = preCdefs bcs
43 liftIO $ writeFile (f ++ ".c") code
44 where checkMVs = do i <- get
45 case idris_metavars i \\ primDefs of
47 ms -> fail $ "There are undefined metavariables: " ++ show ms
48 inDir d h = do let f = d </> h
50 if ex then return f else return h
53mainFn ps tm = toSC ps (MN 0 "_main", Function undefined tm)
55allNames :: [Name] -> Name -> Idris [Name]
56allNames ns n | n `elem` ns = return []
57allNames ns n = do i <- get
58 case lookupCtxt Nothing n (idris_callgraph i) of
59 [ns'] -> do more <- mapM (allNames (n:ns)) ns'
60 return (nub (n : concat more))
63mkDecls :: Term -> [Name] -> Idris [(Name, SCDef)]
66 let ds = filter (\ (n, d) -> n `elem` used) $ ctxtAlist (tt_ctxt i)
67 return $ concatMap (toSC (idris_scprims i)) ds
69cdefs :: [(Name, (Int, PreC))] -> String
70cdefs xs = concatMap (\ (n, (i, c)) -> proto n) xs ++ "\n" ++
71 concatMap (\ (n, (i, c)) -> codegenC n i c) xs
73codegenC :: Name -> Int -> PreC -> String
75 = "/* " ++ show prec ++ " */\n\n" ++
76 "void " ++ cname n ++ "(VM* vm) {\n" ++
77 indent 1 ++ "int i;\n" ++
78 concatMap (cg 1) prec ++ "}\n\n"
80indent i = take (i * 4) (repeat ' ')
83reg (LVar v) = "*(vm->valstack_ptr-" ++ show v ++ ")"
85catom :: CAtom -> String
86catom (CL l) = reg (LVar l)
87catom (CC (I i)) = "MKINT(" ++ show i ++ ")"
88catom (CC v) = "const(" ++ show v ++ ")"
89catom (CP n i) = "MKCLOSURE(" ++ cname n ++ ", " ++ show i ++ ")"
91off o (CL i) = CL (i + o)
95 = indent i ++ reg r ++ " = MKCON(" ++ show tag ++ ", " ++
96 show (length args) ++ ");\n" ++
97 indent i ++ setArgs 0 args ++ "\n"
100 setArgs i (a : as) = "SETARG(" ++ reg r ++ ", " ++
101 show i ++ ", " ++ catom a ++ "); "
102 ++ setArgs (i + 1) as
105 = indent i ++ "EXTEND(" ++ show (length args) ++ ");\n" ++
106 indent i ++ setArgs 1 (map (off (length args)) (reverse args)) ++ "\n" ++
107 indent i ++ cname f ++ "(vm);\n" ++
108 indent i ++ "CLEAR(" ++ show (length args) ++ ");\n" ++
111 r -> indent i ++ reg r ++ " = " ++ reg RVal ++ "\n"
114 setArgs i (a : as) = reg (LVar i) ++ " = " ++ catom a ++ "; "
115 ++ setArgs (i + 1) as
117assignClosure i lazy r atom args
118 = indent i ++ reg r ++ " = APPLY(" ++ catom atom ++ ", " ++ show (length args) ++
120 indent i ++ setArgs 0 args ++ "\n" ++
122 indent i ++ "if (READY(" ++ reg r ++ ")) {\n" ++
123 indent (i + 1) ++ reg r ++ " = EVAL(" ++ reg r ++ ");\n" ++
124 indent i ++ "} else {\n" ++
125 indent (i + 1) ++ "// do nothing \n" ++
130 setArgs i (a : as) = "ADDARG(" ++ show i ++ ", " ++ reg r ++ ", " ++ catom a ++ "); "
131 ++ setArgs (i + 1) as
134 = indent i ++ "EXTEND(" ++ show (length args) ++ ");\n" ++
135 indent i ++ setArgs 1 (map (off (length args)) (reverse args)) ++ "\n" ++
136 indent i ++ "SLIDE(" ++ show d ++ ", " ++ show (length args) ++ ");\n" ++
137 indent i ++ cname f ++ "(vm); return;\n"
140 setArgs i (a : as) = reg (LVar i) ++ " = " ++ catom a ++ "; "
141 ++ setArgs (i + 1) as
143assignFCall i r cfn rt args
144 = indent i ++ reg r ++ " = " ++ fromC rt ++
146 cfn ++ "(" ++ showSep ", " (map toCa args) ++ "))" ++ ";\n"
147 where fromC (Just IType) = "MKINT"
148 fromC (Just StrType) = "MKSTR"
151 toC (Just IType) = "GETINT"
152 toC (Just StrType) = "GETSTR"
155 toCa (a, ty) = toC ty ++ "(" ++ catom a ++ ")"
157assignPrimOp i r p args
158 = indent i ++ reg r ++ " = " ++ op p args ++ ";\n"
160cg :: Int -> CInst -> String
161cg i (ASSIGN r (CCon t args))
162 = assignCon i r t args
163cg i (ASSIGN r (CExactApp f args))
164 = assignFn i r f args
165cg i (ASSIGN r (CApp f args))
166 = assignClosure i False r f args
167cg i (ASSIGN r (CLazy f args))
168 = assignClosure i True r f args
169cg i (ASSIGN r (CFCall cfn rt args))
170 = assignFCall i r cfn rt args
171cg i (ASSIGN r (CPrimOp p args))
172 = assignPrimOp i r p args
173cg i (ASSIGN r (CAtom e)) = indent i ++ reg r ++ " = " ++ catom e ++ ";\n"
174cg i (RESERVE s) = indent i ++ "EXTEND(" ++ show s ++ ");\n"
175cg i (CLEAR s) = indent i ++ "CLEAR(" ++ show s ++ ");\n"
176cg i (EVAL e) = indent i ++ "EVAL(" ++ reg (LVar e) ++ ");\n"
177cg i (PROJECT scr loc num)
178 = indent i ++ "PROJECT(" ++ reg (LVar scr) ++ ", " ++
179 reg (LVar loc) ++ ", " ++ show num ++ ");\n"
180cg i (SWITCH v bs def)
181 = indent i ++ "switch(" ++ sval v ++ ") {\n" ++
182 concatMap branch bs ++
183 indent i ++ "default:\n" ++ concatMap (cg (i+1)) def ++
184 indent (i+1) ++ "break;\n" ++
186 where sval (CTag l) = "TAG(" ++ reg (LVar l) ++ ")"
187 sval (CIntVal l) = "GETINT(" ++ reg (LVar l) ++ ")"
189 branch (t, c) = indent i ++ "case " ++ show t ++ ":\n" ++
190 concatMap (cg (i+1)) c ++
191 indent (i+1) ++ "break;\n"
192cg i (TAILCALL d f args) = assignClosure i False RVal f args -- doTailClosure i d f args
193cg i (TAILCALLEXACT d f args) = doTailCall i d f args
194cg i (ERROR s) = indent i ++ "ERROR(" ++ show s ++ ")\n";
195cg i x = trace (show x ++ " not done") $ indent i ++ "NOT DONE;\n"
197cname :: Name -> String
198cname (UN s) = "_I_" ++ toC s
199cname (MN i s) = "_M_I_" ++ show i ++ "_" ++ toC s
200cname (NS n ss) = "_" ++ showSep "_" (map toC ss) ++ cname n
202toC s = concatMap special s
203 where special c | isAlphaNum c = [c]
205 | otherwise = "_" ++ show (fromEnum c) ++ "_"
207proto :: Name -> String
208proto n = "void " ++ cname n ++ "(VM* vm);\n"
210op AddI [l, r] = "INTOP(+, " ++ catom l ++ ", " ++ catom r ++ ")"
211op SubI [l, r] = "INTOP(-, " ++ catom l ++ ", " ++ catom r ++ ")"
212op MulI [l, r] = "INTOP(*, " ++ catom l ++ ", " ++ catom r ++ ")"
213op DivI [l, r] = "INTOP(/, " ++ catom l ++ ", " ++ catom r ++ ")"
215op ConcatS [l,r] = "CONCAT(" ++ catom l ++ ", " ++ catom r ++ ")"
217op o args = trace (show (op, args) ++ " operator undefined")
218 $ "0 /* Op not defined " ++ show o ++ " */"
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