1 implementation module Data.GenType.CParser
4 import Control.Applicative
5 import Control.Monad => qualified join
6 import Control.Monad.State
7 import Control.Monad.Trans
8 import Control.Monad.Writer
9 import Control.Monad.Fail
17 import Data.GenType.CType
19 instance MonadFail (Either String) where fail s = Left s
20 :: FPMonad :== WriterT [String] (Either String) ()
22 indent i c = tell [createArray i '\t':c]
25 (<.>) a b = a +++ "." +++ b
28 * Generate a single parser for a type.
29 * This does not terminate for a recursive type
31 flatParser :: Type -> Either String ([String], [String])
32 flatParser t = tuple header <$> execWriterT (tell head >>| fpd t True "r" 1 >>| tell tail)
34 includes = "#include <stdint.h>\n#include <stdbool.h>\n"
35 header = [includes:parsefun [";\n"]]
36 parsefun c = [prefix t, safe (typeName t), " parse_", safe (typeName t), "(uint8_t (*get)(void))":c]
37 head = [includes:parsefun [" {\n\t", prefix t, safe (typeName t), " r;\n\n"]]
38 tail = ["\treturn r;\n}\n"]
39 parsename s = "parse_" +++ safe s
40 result r op i s = indent i [r, " ", op, " ", s, ";\n"]
41 assign r i s = result r "=" i s
43 fpd :: Type Bool String Int -> FPMonad
44 fpd (TyRef s) tl r i = assign r i (parsename s)
45 fpd (TyBasic t) tl r i
48 BTInt = assign r i "(int64_t)get()<<54"
49 >>| result r "+=" i "(int64_t)get()<<48"
50 >>| result r "+=" i "(int64_t)get()<<40"
51 >>| result r "+=" i "(int64_t)get()<<32"
52 >>| result r "+=" i "(int64_t)get()<<24"
53 >>| result r "+=" i "(int64_t)get()<<16"
54 >>| result r "+=" i "(int64_t)get()<<8"
55 >>| result r "+=" i "(int64_t)get()"
56 BTChar = assign r i "(char)get()"
57 BTReal = assign r i "double"
58 BTBool = assign r i "(bool)get()"
59 t = fail $ "flatParse: there is no basic type for " +++ toString t
60 fpd (TyArrow _ _) tl r i = fail $ "flatParser: function cannot be serialized"
61 fpd (TyNewType ti ci a) tl r i = fpd a tl r i
62 fpd (TyArray _ _) tl r i = fail $ "flatParser: arrays are not supported since they require dynamic memory"
63 fpd (TyRecord ti fs) tl r i
64 = mapM_ (fmtField i) [(r <.> fi.gfd_name, ty)\\(fi, ty)<-fs]
66 fpd (TyObject ti fs) tl r i
67 | and [t =: [] \\ (_, t)<-fs]
68 = assign r i $ "(" +++ consName ti +++ ") get()"
69 //Single constructor, single field (box)
70 fpd (TyObject ti [(ci, [ty])]) tl r i = fpd ty tl r i
72 fpd (TyObject ti [(ci, ts)]) tl r i
73 = mapM_ (fmtField i) [(r <.> "f" +++ toString i, ty)\\i<-[0..] & ty<-ts]
75 fpd (TyObject ti fs) tl r i
76 = assign (r +++ ".cons") i ("(" +++ consName ti +++ ") get()")
77 >>| indent i ["switch (", r <.> "cons){\n"]
78 >>| mapM_ (fmtCons i) fs
81 fmtCons i (ci, ts) = indent i ["case ", safe ci.gcd_name, ":\n"]
82 >>| mapM_ (fmtField $ i+1) [(cs i, ty) \\i<-[0..] & ty<-ts]
83 >>| indent (i+1) ["break;\n"]
85 cs i = r <.> "data" <.> safe ci.gcd_name +++ if (ts=:[_]) "" (".f" +++ toString i)
86 fpd t tl r i = fail $ "flatParser: unsupported " +++ toString t
88 fmtField :: Int (String, Type) -> FPMonad
89 fmtField i (name, ty) = fpd ty False name i
92 * generate parsers for the types grouped by strongly connected components
94 parser :: [[Type]] -> Either String [String]