{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE OverloadedStrings #-}
module BNFC.Backend.C.CFtoCAbs (cf2CAbs) where
import Prelude hiding ((<>))
import Control.Monad.State (State, gets, modify, evalState)
import Data.Char ( toLower )
import Data.Either ( lefts )
import Data.Function ( on )
import Data.List ( groupBy, intercalate, intersperse, nub, sort )
import Data.Maybe ( mapMaybe )
import Data.Set ( Set )
import qualified Data.Set as Set
import BNFC.CF
import BNFC.PrettyPrint
import BNFC.Options ( RecordPositions(..) )
import BNFC.Utils ( (+++), unless )
import BNFC.Backend.Common.NamedVariables
import BNFC.Backend.C.Common ( posixC )
cf2CAbs
:: RecordPositions
-> String
-> CF
-> (String, String)
cf2CAbs :: RecordPositions -> [Char] -> CF -> ([Char], [Char])
cf2CAbs RecordPositions
rp [Char]
_ CF
cf = (RecordPositions -> [[Char]] -> [Data] -> CF -> [Char]
mkHFile RecordPositions
rp [[Char]]
classes [Data]
datas CF
cf, [Data] -> CF -> [Char]
mkCFile [Data]
datas CF
cf)
where
datas :: [Data]
datas :: [Data]
datas = CF -> [Data]
getAbstractSyntax CF
cf
classes :: [String]
classes :: [[Char]]
classes = forall a. Eq a => [a] -> [a]
nub forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (Cat -> [Char]
identCat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) [Data]
datas
mkHFile :: RecordPositions -> [String] -> [Data] -> CF -> String
mkHFile :: RecordPositions -> [[Char]] -> [Data] -> CF -> [Char]
mkHFile RecordPositions
rp [[Char]]
classes [Data]
datas CF
cf = [[Char]] -> [Char]
unlines forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [ [Char]
"#ifndef ABSYN_HEADER"
, [Char]
"#define ABSYN_HEADER"
, [Char]
""
]
, [[Char]]
posixC
, [ [Char]
""
, [Char]
"#include <stddef.h> /* NULL */"
, [Char]
"#include <string.h> /* strdup */"
, [Char]
""
, [Char]
"/* C++ Abstract Syntax Interface.*/"
, [Char]
""
, [[Char]] -> [Char]
prTypeDefs [[Char]]
user
, [Char]
"/******************** Forward Declarations ***********************/"
]
, forall a b. (a -> b) -> [a] -> [b]
map [Char] -> [Char]
prForward [[Char]]
classes
, [ [Char]
"/******************** Abstract Syntax Classes ********************/"
, [Char]
""
]
, forall a b. (a -> b) -> [a] -> [b]
map (RecordPositions -> Data -> [Char]
prDataH RecordPositions
rp) [Data]
datas
, forall m. Monoid m => Bool -> m -> m
unless (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Char]]
classes) forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [[Char]]
cloneComment
, forall a b. (a -> b) -> [a] -> [b]
map [Char] -> [Char]
prCloneH [[Char]]
classes
, [ [Char]
"" ]
]
, forall m. Monoid m => Bool -> m -> m
unless (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Char]]
classes) forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [[Char]]
destructorComment
, forall a b. (a -> b) -> [a] -> [b]
map [Char] -> [Char]
prFreeH [[Char]]
classes
, [ [Char]
"" ]
]
, forall m. Monoid m => Bool -> m -> m
unless (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Define]
definedConstructors)
[ [Char]
"/******************** Defined Constructors ***********************/"
, [Char]
""
]
, forall a. a -> [a] -> [a]
intersperse [Char]
"" forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map ([[Char]] -> Define -> [Char]
prDefH [[Char]]
user) [Define]
definedConstructors
, [ [Char]
""
, [Char]
"#endif"
]
]
where
user :: [TokenCat]
user :: [[Char]]
user = forall f. CFG f -> [[Char]]
tokenNames CF
cf
prForward :: String -> String
prForward :: [Char] -> [Char]
prForward [Char]
s = [[Char]] -> [Char]
unlines
[ [Char]
"struct " forall a. [a] -> [a] -> [a]
++ [Char]
s forall a. [a] -> [a] -> [a]
++ [Char]
"_;"
, [Char]
"typedef struct " forall a. [a] -> [a] -> [a]
++ [Char]
s forall a. [a] -> [a] -> [a]
++ [Char]
"_ *" forall a. [a] -> [a] -> [a]
++ [Char]
s forall a. [a] -> [a] -> [a]
++ [Char]
";"
]
prCloneH :: String -> String
prCloneH :: [Char] -> [Char]
prCloneH [Char]
s = [Char]
s forall a. [a] -> [a] -> [a]
++ [Char]
" clone_" forall a. [a] -> [a] -> [a]
++ [Char]
s forall a. [a] -> [a] -> [a]
++ [Char]
"(" forall a. [a] -> [a] -> [a]
++ [Char]
s forall a. [a] -> [a] -> [a]
++ [Char]
" p);"
prFreeH :: String -> String
prFreeH :: [Char] -> [Char]
prFreeH [Char]
s = [Char]
"void free_" forall a. [a] -> [a] -> [a]
++ [Char]
s forall a. [a] -> [a] -> [a]
++ [Char]
"(" forall a. [a] -> [a] -> [a]
++ [Char]
s forall a. [a] -> [a] -> [a]
++ [Char]
" p);"
definedConstructors :: [Define]
definedConstructors = forall f. CFG f -> [Define]
definitions CF
cf
cloneComment :: [String]
=
[ [Char]
"/*************************** Cloning ******************************/"
, [Char]
""
]
destructorComment :: [String]
=
[ [Char]
"/******************** Recursive Destructors **********************/"
, [Char]
""
, [Char]
"/* These free an entire abstract syntax tree"
, [Char]
" * including all subtrees and strings."
, [Char]
" *"
, [Char]
" * Will not work properly if there is sharing in the tree,"
, [Char]
" * i.e., when some pointers are aliased. In this case"
, [Char]
" * it will attempt to free the same memory twice."
, [Char]
" */"
, [Char]
""
]
prDefH
:: [TokenCat]
-> Define
-> String
prDefH :: [[Char]] -> Define -> [Char]
prDefH [[Char]]
tokenCats (Define RFun
fun Telescope
args Exp
e Base
_t) =
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ [Char]
"#define make_", [Char]
f, [Char]
"(", forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"," [[Char]]
xs, [Char]
") \\\n ", Exp -> State (Set [Char]) [Char]
prExp Exp
e forall s a. State s a -> s -> a
`evalState` forall a. Monoid a => a
mempty ]
where
f :: [Char]
f = forall a. IsFun a => a -> [Char]
funName RFun
fun
xs :: [[Char]]
xs = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst Telescope
args
toCat :: Base -> Cat
toCat :: Base -> Cat
toCat = [[Char]] -> Base -> Cat
catOfType forall a b. (a -> b) -> a -> b
$ [[Char]]
specialCatsP forall a. [a] -> [a] -> [a]
++ [[Char]]
tokenCats
prExp :: Exp -> State (Set String) String
prExp :: Exp -> State (Set [Char]) [Char]
prExp = \case
Var [Char]
x -> forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets (forall a. Ord a => a -> Set a -> Bool
Set.member [Char]
x) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
False -> [Char]
x forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify (forall a. Ord a => a -> Set a -> Set a
Set.insert [Char]
x)
Bool
True -> case forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup [Char]
x Telescope
args of
Just Base
t -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Cat -> [Char] -> [Char]
cloner (Base -> Cat
toCat Base
t) [Char]
x
Maybe Base
Nothing -> forall a. HasCallStack => a
undefined
App [Char]
g Type
_ [Exp
e] | [Char]
g forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[Char]]
tokenCats
-> Exp -> State (Set [Char]) [Char]
prExp Exp
e
App [Char]
"[]" Type
_ [] -> forall (m :: * -> *) a. Monad m => a -> m a
return [Char]
"NULL"
App [Char]
g Type
t [Exp]
es -> do
[[Char]]
es' <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Exp -> State (Set [Char]) [Char]
prExp [Exp]
es
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ [Char]
"make_", [Char] -> Type -> [Char]
con [Char]
g Type
t, forall {f}. [Exp' f] -> [Char]
lparen [Exp]
es, forall a. [a] -> [[a]] -> [a]
intercalate [Char]
", " [[Char]]
es', [Char]
")" ]
LitInt Integer
i -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> [Char]
show Integer
i
LitDouble Double
d -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> [Char]
show Double
d
LitChar Char
c -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> [Char]
show Char
c
LitString [Char]
s -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ [Char]
"strdup(", forall a. Show a => a -> [Char]
show [Char]
s, [Char]
")" ]
con :: [Char] -> Type -> [Char]
con [Char]
g ~(FunT [Base]
_ts Base
t)
| forall a. IsFun a => a -> Bool
isConsFun [Char]
g = Base -> [Char]
identType Base
t
| Bool
otherwise = [Char]
g
lparen :: [Exp' f] -> [Char]
lparen = \case
Exp' f
_:Exp' f
_:[Exp' f]
_ -> [Char]
" ("
[App f
_ Type
_ (Exp' f
_:[Exp' f]
_)] -> [Char]
" ("
[Exp' f]
_ -> [Char]
"("
prDataH :: RecordPositions -> Data -> String
prDataH :: RecordPositions -> Data -> [Char]
prDataH RecordPositions
rp (Cat
cat, [([Char], [Cat])]
rules)
| Cat -> Bool
isList Cat
cat = [[Char]] -> [Char]
unlines
[ [Char]
"struct " forall a. [a] -> [a] -> [a]
++ [Char]
c' forall a. [a] -> [a] -> [a]
++ [Char]
"_"
, [Char]
"{"
, [Char]
" " forall a. [a] -> [a] -> [a]
++ [Char]
mem [Char] -> [Char] -> [Char]
+++ [Char] -> [Char]
varName [Char]
mem forall a. [a] -> [a] -> [a]
++ [Char]
";"
, [Char]
" " forall a. [a] -> [a] -> [a]
++ [Char]
c' [Char] -> [Char] -> [Char]
+++ [Char] -> [Char]
varName [Char]
c' forall a. [a] -> [a] -> [a]
++ [Char]
";"
, [Char]
"};"
, [Char]
""
, [Char]
c' forall a. [a] -> [a] -> [a]
++ [Char]
" make_" forall a. [a] -> [a] -> [a]
++ [Char]
c' forall a. [a] -> [a] -> [a]
++ [Char]
"(" forall a. [a] -> [a] -> [a]
++ [Char]
mem forall a. [a] -> [a] -> [a]
++ [Char]
" p1, " forall a. [a] -> [a] -> [a]
++ [Char]
c' forall a. [a] -> [a] -> [a]
++ [Char]
" p2);"
]
| Bool
otherwise = [[Char]] -> [Char]
unlines forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [ [Char]
"struct " forall a. [a] -> [a] -> [a]
++ Cat -> [Char]
identCat Cat
cat forall a. [a] -> [a] -> [a]
++ [Char]
"_"
, [Char]
"{"
]
, [ [Char]
" int line_number, char_number;" | RecordPositions
rp forall a. Eq a => a -> a -> Bool
== RecordPositions
RecordPositions ]
, [ [Char]
" enum { " forall a. [a] -> [a] -> [a]
++ forall a. [a] -> [[a]] -> [a]
intercalate [Char]
", " (forall a b. (a -> b) -> [a] -> [b]
map forall {b}. ([Char], b) -> [Char]
prKind [([Char], [Cat])]
rules) forall a. [a] -> [a] -> [a]
++ [Char]
" } kind;"
, [Char]
" union"
, [Char]
" {"
, forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Char], [Cat]) -> [Char]
prUnion [([Char], [Cat])]
rules forall a. [a] -> [a] -> [a]
++ [Char]
" } u;"
, [Char]
"};"
, [Char]
""
]
, forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Cat -> ([Char], [Cat]) -> [[Char]]
prRuleH Cat
cat) [([Char], [Cat])]
rules
]
where
c' :: [Char]
c' = Cat -> [Char]
identCat (Cat -> Cat
normCat Cat
cat)
mem :: [Char]
mem = Cat -> [Char]
identCat (Cat -> Cat
normCatOfList Cat
cat)
prKind :: ([Char], b) -> [Char]
prKind ([Char]
fun, b
_) = [Char]
"is_" forall a. [a] -> [a] -> [a]
++ [Char]
fun
prUnion :: ([Char], [Cat]) -> [Char]
prUnion ([Char]
_, []) = [Char]
""
prUnion ([Char]
fun, [Cat]
cats) = [Char]
" struct { " forall a. [a] -> [a] -> [a]
++ (Doc -> [Char]
render forall a b. (a -> b) -> a -> b
$ [IVar] -> Doc
prInstVars ([Cat] -> [IVar]
getVars [Cat]
cats)) forall a. [a] -> [a] -> [a]
++ [Char]
" } " forall a. [a] -> [a] -> [a]
++ ([Char] -> [Char]
memName [Char]
fun) forall a. [a] -> [a] -> [a]
++ [Char]
";\n"
prRuleH :: Cat -> (Fun, [Cat]) -> [String]
prRuleH :: Cat -> ([Char], [Cat]) -> [[Char]]
prRuleH Cat
c ([Char]
fun, [Cat]
cats)
| forall a. IsFun a => a -> Bool
isNilFun [Char]
fun Bool -> Bool -> Bool
|| forall a. IsFun a => a -> Bool
isOneFun [Char]
fun Bool -> Bool -> Bool
|| forall a. IsFun a => a -> Bool
isConsFun [Char]
fun = []
| Bool
otherwise = forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ Cat -> [Char]
catToStr Cat
c, [Char]
" make_", [Char]
fun, [Char]
"(", forall a. [([Char], a)] -> [Char]
prParamsH ([Cat] -> [IVar]
getVars [Cat]
cats), [Char]
");" ]
where
prParamsH :: [(String, a)] -> String
prParamsH :: forall a. [([Char], a)] -> [Char]
prParamsH [] = [Char]
"void"
prParamsH [([Char], a)]
ps = forall a. [a] -> [[a]] -> [a]
intercalate [Char]
", " forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall {a} {b}. Show a => ([Char], b) -> a -> [Char]
par [([Char], a)]
ps [Int
0::Int ..]
where par :: ([Char], b) -> a -> [Char]
par ([Char]
t, b
_) a
n = [Char]
t forall a. [a] -> [a] -> [a]
++ [Char]
" p" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show a
n
prTypeDefs :: [String] -> String
prTypeDefs :: [[Char]] -> [Char]
prTypeDefs [[Char]]
user = [[Char]] -> [Char]
unlines forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [ [Char]
"/******************** TypeDef Section ********************/"
, [Char]
""
, [Char]
"typedef int Integer;"
, [Char]
"typedef char Char;"
, [Char]
"typedef double Double;"
, [Char]
"typedef char* String;"
, [Char]
"typedef char* Ident;"
]
, forall a b. (a -> b) -> [a] -> [b]
map [Char] -> [Char]
prUserDef [[Char]]
user
]
where
prUserDef :: [Char] -> [Char]
prUserDef [Char]
s = [Char]
"typedef char* " forall a. [a] -> [a] -> [a]
++ [Char]
s forall a. [a] -> [a] -> [a]
++ [Char]
";"
prInstVars :: [IVar] -> Doc
prInstVars :: [IVar] -> Doc
prInstVars =
[Doc] -> Doc
hsep forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map [IVar] -> Doc
prInstVarsOneType forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> a -> Bool) -> [a] -> [[a]]
groupBy (forall a. Eq a => a -> a -> Bool
(==) forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` forall a b. (a, b) -> a
fst) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => [a] -> [a]
sort
where
prInstVarsOneType :: [IVar] -> Doc
prInstVarsOneType [IVar]
ivars = [Char] -> Doc
text (forall a b. (a, b) -> a
fst (forall a. [a] -> a
head [IVar]
ivars))
Doc -> Doc -> Doc
<+> [Doc] -> Doc
hsep (Doc -> [Doc] -> [Doc]
punctuate Doc
comma (forall a b. (a -> b) -> [a] -> [b]
map IVar -> Doc
prIVar [IVar]
ivars))
Doc -> Doc -> Doc
<> Doc
semi
prIVar :: IVar -> Doc
prIVar ([Char]
s, Int
i) = [Char] -> Doc
text ([Char] -> [Char]
varName [Char]
s) Doc -> Doc -> Doc
<> [Char] -> Doc
text (Int -> [Char]
showNum Int
i)
mkCFile :: [Data] -> CF -> String
mkCFile :: [Data] -> CF -> [Char]
mkCFile [Data]
datas CF
_cf = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [Char]
header
, Doc -> [Char]
render forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
vsep forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Data -> [Doc]
prDataC [Data]
datas
, [[Char]] -> [Char]
unlines [ [Char]
"", [Char]
"" ]
, [[Char]] -> [Char]
unlines [[Char]]
cloneComment
, [[Char]] -> [Char]
unlines forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Data -> [[Char]]
prCloneC [Data]
datas
, [[Char]] -> [Char]
unlines [[Char]]
destructorComment
, [[Char]] -> [Char]
unlines forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Data -> [[Char]]
prDestructorC [Data]
datas
]
where
header :: [Char]
header = [[Char]] -> [Char]
unlines
[ [Char]
"/* C Abstract Syntax Implementation. */"
, [Char]
""
, [Char]
"#include <stdio.h>"
, [Char]
"#include <stdlib.h>"
, [Char]
"#include \"Absyn.h\""
, [Char]
""
]
prCloneC :: Data -> [String]
prCloneC :: Data -> [[Char]]
prCloneC (Cat
cat, [([Char], [Cat])]
rules)
| Cat -> Bool
isList Cat
cat =
[ [Char]
cl forall a. [a] -> [a] -> [a]
++ [Char]
" clone_" forall a. [a] -> [a] -> [a]
++ [Char]
cl forall a. [a] -> [a] -> [a]
++ [Char]
"("forall a. [a] -> [a] -> [a]
++ [Char]
cl [Char] -> [Char] -> [Char]
+++ [Char]
vname forall a. [a] -> [a] -> [a]
++ [Char]
")"
, [Char]
"{"
, [Char]
" if (" forall a. [a] -> [a] -> [a]
++ [Char]
vname forall a. [a] -> [a] -> [a]
++ [Char]
")"
, [Char]
" {"
, [Char]
" /* clone of non-empty list */"
, Doc -> [Char]
render forall a b. (a -> b) -> a -> b
$ Int -> Doc -> Doc -> Doc -> Doc -> [Doc] -> Doc
prettyList Int
6 ([Char] -> Doc
text forall a b. (a -> b) -> a -> b
$ [Char]
" return make_" forall a. [a] -> [a] -> [a]
++ [Char]
cl) Doc
"(" Doc
");" Doc
","
[ [Char] -> Doc
text forall a b. (a -> b) -> a -> b
$ [Char]
visitMember
, [Char] -> Doc
text forall a b. (a -> b) -> a -> b
$ [Char]
"clone_" forall a. [a] -> [a] -> [a]
++ [Char]
cl forall a. [a] -> [a] -> [a]
++ [Char]
"(" forall a. [a] -> [a] -> [a]
++ [Char]
vname forall a. [a] -> [a] -> [a]
++ [Char]
"->" forall a. [a] -> [a] -> [a]
++ [Char]
vname forall a. [a] -> [a] -> [a]
++ [Char]
"_)"
]
, [Char]
" }"
, [Char]
" else return NULL; /* clone of empty list */"
, [Char]
"}"
, [Char]
""
]
| Bool
otherwise = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [ [Char]
cl forall a. [a] -> [a] -> [a]
++ [Char]
" clone_" forall a. [a] -> [a] -> [a]
++ [Char]
cl forall a. [a] -> [a] -> [a]
++ [Char]
"(" forall a. [a] -> [a] -> [a]
++ [Char]
cl forall a. [a] -> [a] -> [a]
++ [Char]
" p)"
, [Char]
"{"
, [Char]
" switch(p->kind)"
, [Char]
" {"
]
, forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Char], [Cat]) -> [[Char]]
prCloneRule [([Char], [Cat])]
rules
, [ [Char]
" default:"
, [Char]
" fprintf(stderr, \"Error: bad kind field when cloning " forall a. [a] -> [a] -> [a]
++ [Char]
cl forall a. [a] -> [a] -> [a]
++ [Char]
"!\\n\");"
, [Char]
" exit(1);"
, [Char]
" }"
, [Char]
"}"
, [Char]
""
]
]
where
cl :: [Char]
cl = Cat -> [Char]
identCat Cat
cat
vname :: [Char]
vname = forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower [Char]
cl
visitMember :: String
visitMember :: [Char]
visitMember = Cat -> [Char] -> [Char]
cloner Cat
el forall a b. (a -> b) -> a -> b
$ [Char]
vname forall a. [a] -> [a] -> [a]
++ [Char]
"->" forall a. [a] -> [a] -> [a]
++ [Char]
member forall a. [a] -> [a] -> [a]
++ [Char]
"_"
where
el :: Cat
el = Cat -> Cat
normCatOfList Cat
cat
member :: [Char]
member = forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower forall a b. (a -> b) -> a -> b
$ Cat -> [Char]
identCat Cat
el
prCloneRule :: (String, [Cat]) -> [String]
prCloneRule :: ([Char], [Cat]) -> [[Char]]
prCloneRule ([Char]
fun, [Cat]
cats) | Bool -> Bool
not (forall a. IsFun a => a -> Bool
isCoercion [Char]
fun) =
[ [Char]
" case is_" forall a. [a] -> [a] -> [a]
++ [Char]
fnm forall a. [a] -> [a] -> [a]
++ [Char]
":"
, Doc -> [Char]
render forall a b. (a -> b) -> a -> b
$ Int -> Doc -> Doc -> Doc -> Doc -> [Doc] -> Doc
prettyList Int
6 ([Char] -> Doc
text forall a b. (a -> b) -> a -> b
$ [Char]
" return make_" forall a. [a] -> [a] -> [a]
++ [Char]
fnm) Doc
"(" Doc
");\n" Doc
"," forall a b. (a -> b) -> a -> b
$
forall a b. (a -> b) -> [a] -> [b]
map ([Char] -> Doc
text forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> (Cat, Doc) -> [Char]
prCloneCat [Char]
fnm) forall a b. (a -> b) -> a -> b
$ forall a b. [Either a b] -> [a]
lefts forall a b. (a -> b) -> a -> b
$ forall a. [Either Cat a] -> [Either (Cat, Doc) a]
numVars forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall a b. a -> Either a b
Left [Cat]
cats
]
where
fnm :: [Char]
fnm = forall a. IsFun a => a -> [Char]
funName [Char]
fun
prCloneRule ([Char], [Cat])
_ = []
prCloneCat :: String -> (Cat, Doc) -> String
prCloneCat :: [Char] -> (Cat, Doc) -> [Char]
prCloneCat [Char]
fnm (Cat
cat, Doc
nt) = Cat -> [Char] -> [Char]
cloner Cat
cat [Char]
member
where
member :: [Char]
member = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ [Char]
"p->u.", forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower [Char]
fnm, [Char]
"_.", Doc -> [Char]
render Doc
nt ]
cloner :: Cat -> String -> String
cloner :: Cat -> [Char] -> [Char]
cloner Cat
cat [Char]
x =
case Cat
cat of
TokenCat [Char]
c
| [Char]
c forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[Char]
"Char", [Char]
"Double", [Char]
"Integer"]
-> [Char]
x
| Bool
otherwise -> [Char]
"strdup" forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
parens [Char]
x
Cat
_ -> [Char]
"clone_" forall a. [a] -> [a] -> [a]
++ Cat -> [Char]
identCat (Cat -> Cat
normCat Cat
cat) forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
parens [Char]
x
where parens :: [Char] -> [Char]
parens = ([Char]
"(" forall a. [a] -> [a] -> [a]
++) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. [a] -> [a] -> [a]
++ [Char]
")")
prDestructorC :: Data -> [String]
prDestructorC :: Data -> [[Char]]
prDestructorC (Cat
cat, [([Char], [Cat])]
rules)
| Cat -> Bool
isList Cat
cat = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [ [Char]
"void free_" forall a. [a] -> [a] -> [a]
++ [Char]
cl forall a. [a] -> [a] -> [a]
++ [Char]
"("forall a. [a] -> [a] -> [a]
++ [Char]
cl [Char] -> [Char] -> [Char]
+++ [Char]
vname forall a. [a] -> [a] -> [a]
++ [Char]
")"
, [Char]
"{"
, [Char]
" if (" forall a. [a] -> [a] -> [a]
++ [Char]
vname forall a. [a] -> [a] -> [a]
++ [Char]
")"
, [Char]
" {"
]
, forall a b. (a -> b) -> [a] -> [b]
map ([Char]
" " forall a. [a] -> [a] -> [a]
++) [[Char]]
visitMember
, [ [Char]
" free_" forall a. [a] -> [a] -> [a]
++ [Char]
cl forall a. [a] -> [a] -> [a]
++ [Char]
"(" forall a. [a] -> [a] -> [a]
++ [Char]
vname forall a. [a] -> [a] -> [a]
++ [Char]
"->" forall a. [a] -> [a] -> [a]
++ [Char]
vname forall a. [a] -> [a] -> [a]
++ [Char]
"_);"
, [Char]
" free(" forall a. [a] -> [a] -> [a]
++ [Char]
vname forall a. [a] -> [a] -> [a]
++ [Char]
");"
, [Char]
" }"
, [Char]
"}"
, [Char]
""
]
]
| Bool
otherwise = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [ [Char]
"void free_" forall a. [a] -> [a] -> [a]
++ [Char]
cl forall a. [a] -> [a] -> [a]
++ [Char]
"(" forall a. [a] -> [a] -> [a]
++ [Char]
cl forall a. [a] -> [a] -> [a]
++ [Char]
" p)"
, [Char]
"{"
, [Char]
" switch(p->kind)"
, [Char]
" {"
]
, forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Char], [Cat]) -> [[Char]]
prFreeRule [([Char], [Cat])]
rules
, [ [Char]
" default:"
, [Char]
" fprintf(stderr, \"Error: bad kind field when freeing " forall a. [a] -> [a] -> [a]
++ [Char]
cl forall a. [a] -> [a] -> [a]
++ [Char]
"!\\n\");"
, [Char]
" exit(1);"
, [Char]
" }"
, [Char]
" free(p);"
, [Char]
"}"
, [Char]
""
]
]
where
cl :: [Char]
cl = Cat -> [Char]
identCat Cat
cat
vname :: [Char]
vname = forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower [Char]
cl
visitMember :: [[Char]]
visitMember =
case Cat
ecat of
TokenCat [Char]
c
| [Char]
c forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[Char]
"Char", [Char]
"Double", [Char]
"Integer"] -> []
| Bool
otherwise -> [ [Char]
"free" forall a. [a] -> [a] -> [a]
++ [Char]
rest ]
Cat
_ -> [ [Char]
"free_" forall a. [a] -> [a] -> [a]
++ [Char]
ecl forall a. [a] -> [a] -> [a]
++ [Char]
rest ]
where
rest :: [Char]
rest = [Char]
"(" forall a. [a] -> [a] -> [a]
++ [Char]
vname forall a. [a] -> [a] -> [a]
++ [Char]
"->" forall a. [a] -> [a] -> [a]
++ [Char]
member forall a. [a] -> [a] -> [a]
++ [Char]
"_);"
member :: [Char]
member = forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower [Char]
ecl
ecl :: [Char]
ecl = Cat -> [Char]
identCat Cat
ecat
ecat :: Cat
ecat = Cat -> Cat
normCatOfList Cat
cat
prFreeRule :: (String, [Cat]) -> [String]
prFreeRule :: ([Char], [Cat]) -> [[Char]]
prFreeRule ([Char]
fun, [Cat]
cats) | Bool -> Bool
not (forall a. IsFun a => a -> Bool
isCoercion [Char]
fun) = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [ [Char]
" case is_" forall a. [a] -> [a] -> [a]
++ [Char]
fnm forall a. [a] -> [a] -> [a]
++ [Char]
":"
]
, forall a b. (a -> b) -> [a] -> [b]
map ([Char]
" " forall a. [a] -> [a] -> [a]
++) forall a b. (a -> b) -> a -> b
$ forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ([Char] -> (Cat, Doc) -> Maybe [Char]
prFreeCat [Char]
fnm) forall a b. (a -> b) -> a -> b
$ forall a b. [Either a b] -> [a]
lefts forall a b. (a -> b) -> a -> b
$ forall a. [Either Cat a] -> [Either (Cat, Doc) a]
numVars forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall a b. a -> Either a b
Left [Cat]
cats
, [ [Char]
" break;"
, [Char]
""
]
]
where
fnm :: [Char]
fnm = forall a. IsFun a => a -> [Char]
funName [Char]
fun
prFreeRule ([Char], [Cat])
_ = []
prFreeCat :: String -> (Cat, Doc) -> Maybe String
prFreeCat :: [Char] -> (Cat, Doc) -> Maybe [Char]
prFreeCat [Char]
_fnm (TokenCat [Char]
c, Doc
_nt)
| [Char]
c forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[Char]
"Char", [Char]
"Double", [Char]
"Integer"] = forall a. Maybe a
Nothing
prFreeCat [Char]
fnm (Cat
cat, Doc
nt) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ forall b a. b -> (a -> b) -> Maybe a -> b
maybe ([Char]
"free_" forall a. [a] -> [a] -> [a]
++ Cat -> [Char]
identCat (Cat -> Cat
normCat Cat
cat)) (forall a b. a -> b -> a
const [Char]
"free") forall a b. (a -> b) -> a -> b
$ Cat -> Maybe [Char]
maybeTokenCat Cat
cat
, [Char]
"(p->u."
, forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower [Char]
fnm
, [Char]
"_.", Doc -> [Char]
render Doc
nt, [Char]
");"
]
prDataC :: Data -> [Doc]
prDataC :: Data -> [Doc]
prDataC (Cat
cat, [([Char], [Cat])]
rules) = forall a b. (a -> b) -> [a] -> [b]
map (Cat -> ([Char], [Cat]) -> Doc
prRuleC Cat
cat) [([Char], [Cat])]
rules
prRuleC :: Cat -> (String, [Cat]) -> Doc
prRuleC :: Cat -> ([Char], [Cat]) -> Doc
prRuleC Cat
_ ([Char]
fun, [Cat]
_) | forall a. IsFun a => a -> Bool
isNilFun [Char]
fun Bool -> Bool -> Bool
|| forall a. IsFun a => a -> Bool
isOneFun [Char]
fun = Doc
empty
prRuleC cat :: Cat
cat@(ListCat Cat
c') ([Char]
fun, [Cat]
_) | forall a. IsFun a => a -> Bool
isConsFun [Char]
fun = [Doc] -> Doc
vcat'
[ Doc
"/******************** " Doc -> Doc -> Doc
<> Doc
c Doc -> Doc -> Doc
<> Doc
" ********************/"
, Doc
""
, Doc
c Doc -> Doc -> Doc
<+> Doc
"make_" Doc -> Doc -> Doc
<> Doc
c Doc -> Doc -> Doc
<> Doc -> Doc
parens ([Char] -> Doc
text [Char]
m Doc -> Doc -> Doc
<+> Doc
"p1" Doc -> Doc -> Doc
<> Doc
"," Doc -> Doc -> Doc
<+> Doc
c Doc -> Doc -> Doc
<+> Doc
"p2")
, Doc
lbrace
, Int -> Doc -> Doc
nest Int
4 forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
vcat'
[ Doc
c Doc -> Doc -> Doc
<+> Doc
"tmp = (" Doc -> Doc -> Doc
<> Doc
c Doc -> Doc -> Doc
<> Doc
") malloc(sizeof(*tmp));"
, Doc
"if (!tmp)"
, Doc
lbrace
, Int -> Doc -> Doc
nest Int
4 forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
vcat'
[ Doc
"fprintf(stderr, \"Error: out of memory when allocating " Doc -> Doc -> Doc
<> Doc
c Doc -> Doc -> Doc
<> Doc
"!\\n\");"
, Doc
"exit(1);" ]
, Doc
rbrace
, [Char] -> Doc
text forall a b. (a -> b) -> a -> b
$ [Char]
"tmp->" forall a. [a] -> [a] -> [a]
++ [Char]
m' forall a. [a] -> [a] -> [a]
++ [Char]
" = " forall a. [a] -> [a] -> [a]
++ [Char]
"p1;"
, Doc
"tmp->" Doc -> Doc -> Doc
<> Doc
v Doc -> Doc -> Doc
<+> Doc
"=" Doc -> Doc -> Doc
<+> Doc
"p2;"
, Doc
"return tmp;" ]
, Doc
rbrace ]
where
icat :: [Char]
icat = Cat -> [Char]
identCat (Cat -> Cat
normCat Cat
cat)
c :: Doc
c = [Char] -> Doc
text [Char]
icat
v :: Doc
v = [Char] -> Doc
text (forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower [Char]
icat forall a. [a] -> [a] -> [a]
++ [Char]
"_")
m :: [Char]
m = Cat -> [Char]
identCat (Cat -> Cat
normCat Cat
c')
m' :: [Char]
m' = forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower [Char]
m forall a. [a] -> [a] -> [a]
++ [Char]
"_"
prRuleC Cat
c ([Char]
fun, [Cat]
cats) = [Doc] -> Doc
vcat'
[ [Char] -> Doc
text forall a b. (a -> b) -> a -> b
$ [Char]
"/******************** " forall a. [a] -> [a] -> [a]
++ [Char]
fun forall a. [a] -> [a] -> [a]
++ [Char]
" ********************/"
, Doc
""
, Cat -> [Char] -> [IVar] -> [Cat] -> Doc
prConstructorC Cat
c [Char]
fun [IVar]
vs [Cat]
cats ]
where
vs :: [IVar]
vs = [Cat] -> [IVar]
getVars [Cat]
cats
prConstructorC :: Cat -> String -> [IVar] -> [Cat] -> Doc
prConstructorC :: Cat -> [Char] -> [IVar] -> [Cat] -> Doc
prConstructorC Cat
cat [Char]
c [IVar]
vs [Cat]
cats = [Doc] -> Doc
vcat'
[ [Char] -> Doc
text ([Char]
cat' forall a. [a] -> [a] -> [a]
++ [Char]
" make_" forall a. [a] -> [a] -> [a]
++ [Char]
c) Doc -> Doc -> Doc
<> Doc -> Doc
parens Doc
args
, Doc
lbrace
, Int -> Doc -> Doc
nest Int
4 forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
vcat'
[ [Char] -> Doc
text forall a b. (a -> b) -> a -> b
$ [Char]
cat' forall a. [a] -> [a] -> [a]
++ [Char]
" tmp = (" forall a. [a] -> [a] -> [a]
++ [Char]
cat' forall a. [a] -> [a] -> [a]
++ [Char]
") malloc(sizeof(*tmp));"
, [Char] -> Doc
text [Char]
"if (!tmp)"
, Doc
lbrace
, Int -> Doc -> Doc
nest Int
4 forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
vcat'
[ [Char] -> Doc
text ([Char]
"fprintf(stderr, \"Error: out of memory when allocating " forall a. [a] -> [a] -> [a]
++ [Char]
c forall a. [a] -> [a] -> [a]
++ [Char]
"!\\n\");")
, [Char] -> Doc
text [Char]
"exit(1);" ]
, Doc
rbrace
, [Char] -> Doc
text forall a b. (a -> b) -> a -> b
$ [Char]
"tmp->kind = is_" forall a. [a] -> [a] -> [a]
++ [Char]
c forall a. [a] -> [a] -> [a]
++ [Char]
";"
, [Char] -> [IVar] -> [Doc] -> Doc
prAssigns [Char]
c [IVar]
vs [Doc]
params
, [Char] -> Doc
text [Char]
"return tmp;" ]
, Doc
rbrace ]
where
cat' :: [Char]
cat' = Cat -> [Char]
identCat (Cat -> Cat
normCat Cat
cat)
([Doc]
types, [Doc]
params) = forall a b. [(a, b)] -> ([a], [b])
unzip ([Cat] -> [(Doc, Doc)]
prParams [Cat]
cats)
args :: Doc
args = [Doc] -> Doc
hsep forall a b. (a -> b) -> a -> b
$ Doc -> [Doc] -> [Doc]
punctuate Doc
comma forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Doc -> Doc -> Doc
(<+>) [Doc]
types [Doc]
params
prParams :: [Cat] -> [(Doc, Doc)]
prParams :: [Cat] -> [(Doc, Doc)]
prParams = forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall {a}. Show a => a -> Cat -> (Doc, Doc)
prParam [Int
1::Int ..]
where
prParam :: a -> Cat -> (Doc, Doc)
prParam a
n Cat
c = ([Char] -> Doc
text (Cat -> [Char]
identCat Cat
c), [Char] -> Doc
text ([Char]
"p" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show a
n))
prAssigns :: String -> [IVar] -> [Doc] -> Doc
prAssigns :: [Char] -> [IVar] -> [Doc] -> Doc
prAssigns [Char]
c [IVar]
vars [Doc]
params = [Doc] -> Doc
vcat forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith IVar -> Doc -> Doc
prAssign [IVar]
vars [Doc]
params
where
prAssign :: IVar -> Doc -> Doc
prAssign ([Char]
t,Int
n) Doc
p =
[Char] -> Doc
text ([Char]
"tmp->u." forall a. [a] -> [a] -> [a]
++ [Char]
c' forall a. [a] -> [a] -> [a]
++ [Char]
"_." forall a. [a] -> [a] -> [a]
++ [Char] -> Int -> [Char]
vname [Char]
t Int
n) Doc -> Doc -> Doc
<+> Char -> Doc
char Char
'=' Doc -> Doc -> Doc
<+> Doc
p Doc -> Doc -> Doc
<> Doc
semi
vname :: [Char] -> Int -> [Char]
vname [Char]
t Int
n
| Int
n forall a. Eq a => a -> a -> Bool
== Int
1, [IVar
_] <- forall a. (a -> Bool) -> [a] -> [a]
filter (([Char]
t forall a. Eq a => a -> a -> Bool
==) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) [IVar]
vars
= [Char] -> [Char]
varName [Char]
t
| Bool
otherwise = [Char] -> [Char]
varName [Char]
t forall a. [a] -> [a] -> [a]
++ Int -> [Char]
showNum Int
n
c' :: [Char]
c' = forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower [Char]
c
memName :: String -> String
memName :: [Char] -> [Char]
memName [Char]
s = forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower [Char]
s forall a. [a] -> [a] -> [a]
++ [Char]
"_"