{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TupleSections #-}
module BNFC.Backend.Java.CFtoJavaAbs15 (cf2JavaAbs, typename, cat2JavaType) where
import Data.Bifunctor ( first )
import Data.Char ( isUpper, toLower )
import Data.Function ( on )
import Data.List ( findIndices, intercalate )
import Data.Maybe ( mapMaybe )
import System.FilePath ( (</>) )
import Text.PrettyPrint as P
import BNFC.CF
import BNFC.Options ( RecordPositions(..) )
import BNFC.TypeChecker ( buildContext, ctxTokens, isToken )
import BNFC.Utils ( (+++), (++++), unless )
import BNFC.Backend.Common.NamedVariables ( UserDef, showNum )
import BNFC.Backend.Java.Utils ( getRuleName )
type IVar = (String, Int, String)
cf2JavaAbs :: FilePath
-> String -> String -> CF -> RecordPositions -> [(FilePath, String)]
cf2JavaAbs :: FilePath
-> FilePath
-> FilePath
-> CF
-> RecordPositions
-> [(FilePath, FilePath)]
cf2JavaAbs FilePath
dirAbsyn FilePath
packageBase FilePath
packageAbsyn CF
cf RecordPositions
rp = [[(FilePath, FilePath)]] -> [(FilePath, FilePath)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ Bool -> [(FilePath, FilePath)] -> [(FilePath, FilePath)]
forall m. Monoid m => Bool -> m -> m
unless ([Define] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Define]
defs)
[ (FilePath
dirAbsyn FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"Def", [FilePath] -> FilePath
unlines [FilePath]
deftext) ]
, ((FilePath, FilePath) -> (FilePath, FilePath))
-> [(FilePath, FilePath)] -> [(FilePath, FilePath)]
forall a b. (a -> b) -> [a] -> [b]
map ((FilePath -> FilePath)
-> (FilePath, FilePath) -> (FilePath, FilePath)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first FilePath -> FilePath
mkPath) ([(FilePath, FilePath)] -> [(FilePath, FilePath)])
-> [(FilePath, FilePath)] -> [(FilePath, FilePath)]
forall a b. (a -> b) -> a -> b
$ (Data -> [(FilePath, FilePath)])
-> [Data] -> [(FilePath, FilePath)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (RecordPositions
-> FilePath
-> FilePath
-> [FilePath]
-> Data
-> [(FilePath, FilePath)]
prData RecordPositions
rp FilePath
header FilePath
packageAbsyn [FilePath]
user) [Data]
rules
]
where
header :: FilePath
header = FilePath
"package " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
packageAbsyn FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
";\n"
user :: [FilePath]
user = [ FilePath
n | (FilePath
n,Reg
_) <- CF -> [(FilePath, Reg)]
forall f. CFG f -> [(FilePath, Reg)]
tokenPragmas CF
cf ]
rules :: [Data]
rules = CF -> [Data]
getAbstractSyntax CF
cf
defs :: [Define]
defs = CF -> [Define]
forall f. CFG f -> [Define]
definitions CF
cf
deftext :: [FilePath]
deftext= [[FilePath]] -> [FilePath]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [ FilePath
"package " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
packageBase FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
";"
, FilePath
""
, FilePath
"public class AbsynDef {"
, FilePath
""
, FilePath
" public static <B,A extends java.util.LinkedList<? super B>> A cons(B x, A xs) {"
, FilePath
" xs.addFirst(x);"
, FilePath
" return xs;"
, FilePath
" }"
, FilePath
""
]
, [Define] -> FilePath -> CF -> [FilePath]
definedRules [Define]
defs FilePath
packageAbsyn CF
cf
, [ FilePath
"}"]
]
mkPath :: String -> FilePath
mkPath :: FilePath -> FilePath
mkPath FilePath
s = FilePath
dirAbsyn FilePath -> FilePath -> FilePath
</> FilePath
s
definedRules :: [Define] -> String -> CF -> [String]
definedRules :: [Define] -> FilePath -> CF -> [FilePath]
definedRules [Define]
defs FilePath
packageAbsyn CF
cf = (Define -> FilePath) -> [Define] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map Define -> FilePath
rule [Define]
defs
where
ctx :: Context
ctx = CF -> Context
buildContext CF
cf
rule :: Define -> FilePath
rule (Define RFun
f Telescope
args Exp
e Base
t) =
[FilePath] -> FilePath
unlines ([FilePath] -> FilePath) -> [FilePath] -> FilePath
forall a b. (a -> b) -> a -> b
$ (FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath
" " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++) ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$
[ FilePath
"public static " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Base -> FilePath
javaType Base
t FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath -> FilePath
sanitize (RFun -> FilePath
forall a. IsFun a => a -> FilePath
funName RFun
f) FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"(" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++
FilePath -> [FilePath] -> FilePath
forall a. [a] -> [[a]] -> [a]
intercalate FilePath
", " (((FilePath, Base) -> FilePath) -> Telescope -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath, Base) -> FilePath
javaArg Telescope
args) FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
") {"
, FilePath
" return " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ [FilePath] -> Exp -> FilePath
javaExp (((FilePath, Base) -> FilePath) -> Telescope -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath, Base) -> FilePath
forall a b. (a, b) -> a
fst Telescope
args) Exp
e FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
";"
, FilePath
"}"
]
where
sanitize :: FilePath -> FilePath
sanitize = FilePath -> FilePath
getRuleName
javaType :: Base -> String
javaType :: Base -> FilePath
javaType = \case
ListT (BaseT FilePath
x) -> [FilePath] -> FilePath
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ FilePath
packageAbsyn, FilePath
".List", FilePath
x ]
BaseT FilePath
x -> FilePath -> [FilePath] -> FilePath -> FilePath
typename FilePath
packageAbsyn (Context -> [FilePath]
ctxTokens Context
ctx) FilePath
x
ListT ListT{} -> FilePath
forall a. HasCallStack => a
undefined
javaArg :: (String, Base) -> String
javaArg :: (FilePath, Base) -> FilePath
javaArg (FilePath
x,Base
t) = Base -> FilePath
javaType Base
t FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
x
javaExp :: [String] -> Exp -> String
javaExp :: [FilePath] -> Exp -> FilePath
javaExp [FilePath]
args = \case
Var FilePath
x -> FilePath
x
App FilePath
"[]" (FunT [Base]
_ Base
t) []
-> FilePath -> [Exp] -> FilePath
callQ (Base -> FilePath
identType Base
t) []
App FilePath
"(:)" Type
_ [Exp]
es -> FilePath -> [Exp] -> FilePath
call FilePath
"cons" [Exp]
es
App FilePath
t Type
_ [Exp
e]
| FilePath -> Context -> Bool
isToken FilePath
t Context
ctx -> [FilePath] -> Exp -> FilePath
javaExp [FilePath]
args Exp
e
App FilePath
x Type
_ [Exp]
es
| Char -> Bool
isUpper (FilePath -> Char
forall a. [a] -> a
head FilePath
x) -> FilePath -> [Exp] -> FilePath
callQ FilePath
x [Exp]
es
| Bool
otherwise -> FilePath -> [Exp] -> FilePath
call (FilePath -> FilePath
sanitize FilePath
x) [Exp]
es
LitInt Integer
n -> FilePath
"Integer.valueOf(" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Integer -> FilePath
forall a. Show a => a -> FilePath
show Integer
n FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
")"
LitDouble Double
x -> FilePath
"Double.valueOf(" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Double -> FilePath
forall a. Show a => a -> FilePath
show Double
x FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
")"
LitChar Char
c -> FilePath
"Character.valueOf(" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Char -> FilePath
forall a. Show a => a -> FilePath
show Char
c FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
")"
LitString FilePath
s -> FilePath
"String.valueOf(" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath -> FilePath
forall a. Show a => a -> FilePath
show FilePath
s FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
")"
where
call :: FilePath -> [Exp] -> FilePath
call FilePath
x [Exp]
es = FilePath
x FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"(" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath -> [FilePath] -> FilePath
forall a. [a] -> [[a]] -> [a]
intercalate FilePath
", " ((Exp -> FilePath) -> [Exp] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map ([FilePath] -> Exp -> FilePath
javaExp [FilePath]
args) [Exp]
es) FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
")"
callQ :: FilePath -> [Exp] -> FilePath
callQ = FilePath -> [Exp] -> FilePath
call (FilePath -> [Exp] -> FilePath)
-> (FilePath -> FilePath) -> FilePath -> [Exp] -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath
qualify
qualify :: FilePath -> FilePath
qualify FilePath
x = FilePath
"new " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
packageAbsyn FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"." FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
x
prData :: RecordPositions -> String -> String -> [UserDef] -> Data ->[(String, String)]
prData :: RecordPositions
-> FilePath
-> FilePath
-> [FilePath]
-> Data
-> [(FilePath, FilePath)]
prData RecordPositions
rp FilePath
header FilePath
packageAbsyn [FilePath]
user (Cat
cat, [(FilePath, [Cat])]
rules) =
[(FilePath, FilePath)]
categoryClass [(FilePath, FilePath)]
-> [(FilePath, FilePath)] -> [(FilePath, FilePath)]
forall a. [a] -> [a] -> [a]
++ ((FilePath, [Cat]) -> Maybe (FilePath, FilePath))
-> [(FilePath, [Cat])] -> [(FilePath, FilePath)]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (RecordPositions
-> FilePath
-> FilePath
-> [FilePath]
-> [FilePath]
-> Cat
-> (FilePath, [Cat])
-> Maybe (FilePath, FilePath)
prRule RecordPositions
rp FilePath
header FilePath
packageAbsyn [FilePath]
funs [FilePath]
user Cat
cat) [(FilePath, [Cat])]
rules
where
funs :: [FilePath]
funs = ((FilePath, [Cat]) -> FilePath)
-> [(FilePath, [Cat])] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath, [Cat]) -> FilePath
forall a b. (a, b) -> a
fst [(FilePath, [Cat])]
rules
categoryClass :: [(FilePath, FilePath)]
categoryClass
| Cat -> FilePath
catToStr Cat
cat FilePath -> [FilePath] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FilePath]
funs = []
| Bool
otherwise = [(FilePath
cls, FilePath
header FilePath -> FilePath -> FilePath
++++
[FilePath] -> FilePath
unlines [
FilePath
"public abstract class" FilePath -> FilePath -> FilePath
+++ FilePath
cls
FilePath -> FilePath -> FilePath
+++ FilePath
"implements java.io.Serializable {",
FilePath
" public abstract <R,A> R accept("
FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
cls FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
".Visitor<R,A> v, A arg);",
FilePath -> [FilePath] -> FilePath
prVisitor FilePath
packageAbsyn [FilePath]
funs,
FilePath
"}"
])]
where cls :: FilePath
cls = Cat -> FilePath
identCat Cat
cat
prVisitor :: String -> [String] -> String
prVisitor :: FilePath -> [FilePath] -> FilePath
prVisitor FilePath
packageAbsyn [FilePath]
funs =
[FilePath] -> FilePath
unlines [
FilePath
" public interface Visitor <R,A> {",
[FilePath] -> FilePath
unlines ((FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> FilePath
prVisitFun [FilePath]
funs),
FilePath
" }"
]
where
prVisitFun :: FilePath -> FilePath
prVisitFun FilePath
f = FilePath
" public R visit(" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
packageAbsyn FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"." FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
f FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" p, A arg);"
prRule :: RecordPositions
-> String
-> String
-> [String]
-> [UserDef] -> Cat -> (Fun, [Cat]) -> Maybe (String, String)
prRule :: RecordPositions
-> FilePath
-> FilePath
-> [FilePath]
-> [FilePath]
-> Cat
-> (FilePath, [Cat])
-> Maybe (FilePath, FilePath)
prRule RecordPositions
rp FilePath
h FilePath
packageAbsyn [FilePath]
funs [FilePath]
user Cat
c (FilePath
fun, [Cat]
cats)
| FilePath -> Bool
forall a. IsFun a => a -> Bool
isNilFun FilePath
fun Bool -> Bool -> Bool
|| FilePath -> Bool
forall a. IsFun a => a -> Bool
isOneFun FilePath
fun = Maybe (FilePath, FilePath)
forall a. Maybe a
Nothing
| FilePath -> Bool
forall a. IsFun a => a -> Bool
isConsFun FilePath
fun = (FilePath, FilePath) -> Maybe (FilePath, FilePath)
forall a. a -> Maybe a
Just ((FilePath, FilePath) -> Maybe (FilePath, FilePath))
-> ([FilePath] -> (FilePath, FilePath))
-> [FilePath]
-> Maybe (FilePath, FilePath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath
fun',) (FilePath -> (FilePath, FilePath))
-> ([FilePath] -> FilePath) -> [FilePath] -> (FilePath, FilePath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> FilePath
unlines ([FilePath] -> Maybe (FilePath, FilePath))
-> [FilePath] -> Maybe (FilePath, FilePath)
forall a b. (a -> b) -> a -> b
$
[ FilePath
h
, [FilePath] -> FilePath
unwords [ FilePath
"public class", FilePath
fun', FilePath
"extends", [FilePath] -> Cat -> FilePath
cat2JavaTypeTopList [FilePath]
user Cat
c, FilePath
"{" ]
, FilePath
"}"
]
| Bool
otherwise = (FilePath, FilePath) -> Maybe (FilePath, FilePath)
forall a. a -> Maybe a
Just ((FilePath, FilePath) -> Maybe (FilePath, FilePath))
-> ([FilePath] -> (FilePath, FilePath))
-> [FilePath]
-> Maybe (FilePath, FilePath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath
fun,) (FilePath -> (FilePath, FilePath))
-> ([FilePath] -> FilePath) -> [FilePath] -> (FilePath, FilePath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> FilePath
unlines ([FilePath] -> Maybe (FilePath, FilePath))
-> [FilePath] -> Maybe (FilePath, FilePath)
forall a b. (a -> b) -> a -> b
$
[ FilePath
h
, [FilePath] -> FilePath
unwords [ FilePath
"public class", FilePath
fun, FilePath
ext, FilePath
"{" ]
, Doc -> FilePath
render (Doc -> FilePath) -> Doc -> FilePath
forall a b. (a -> b) -> a -> b
$ Int -> Doc -> Doc
nest Int
2 (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
vcat
[ RecordPositions -> [IVar] -> Doc
prInstVars RecordPositions
rp [IVar]
vs
, FilePath -> [FilePath] -> [IVar] -> [Cat] -> Doc
prConstructor FilePath
fun [FilePath]
user [IVar]
vs [Cat]
cats
]
, FilePath -> Cat -> FilePath -> FilePath
prAccept FilePath
packageAbsyn Cat
c FilePath
fun
, FilePath -> FilePath -> [IVar] -> FilePath
prEquals FilePath
packageAbsyn FilePath
fun [IVar]
vs
, FilePath -> FilePath -> [IVar] -> FilePath
prHashCode FilePath
packageAbsyn FilePath
fun [IVar]
vs
, if Bool
isAlsoCategory then FilePath -> [FilePath] -> FilePath
prVisitor FilePath
packageAbsyn [FilePath]
funs else FilePath
""
, FilePath
"}"
]
where
vs :: [IVar]
vs = [Cat] -> [FilePath] -> [IVar]
getVars [Cat]
cats [FilePath]
user
fun' :: FilePath
fun' = Cat -> FilePath
identCat (Cat -> Cat
normCat Cat
c)
isAlsoCategory :: Bool
isAlsoCategory = FilePath
fun FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== Cat -> FilePath
catToStr Cat
c
ext :: FilePath
ext = if Bool
isAlsoCategory then FilePath
"" else FilePath
" extends" FilePath -> FilePath -> FilePath
+++ Cat -> FilePath
identCat Cat
c
prAccept :: String -> Cat -> String -> String
prAccept :: FilePath -> Cat -> FilePath -> FilePath
prAccept FilePath
pack Cat
cat FilePath
_ = FilePath
"\n public <R,A> R accept(" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
pack FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"." FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Cat -> FilePath
catToStr Cat
cat
FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
".Visitor<R,A> v, A arg) { return v.visit(this, arg); }\n"
prEquals :: String -> String -> [IVar] -> String
prEquals :: FilePath -> FilePath -> [IVar] -> FilePath
prEquals FilePath
pack FilePath
fun [IVar]
vs =
[FilePath] -> FilePath
unlines ([FilePath] -> FilePath) -> [FilePath] -> FilePath
forall a b. (a -> b) -> a -> b
$ (FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath
" "FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++) ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ [FilePath
"public boolean equals(java.lang.Object o) {",
FilePath
" if (this == o) return true;",
FilePath
" if (o instanceof " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
fqn FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
") {"]
[FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ (if [IVar] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [IVar]
vs
then [FilePath
" return true;"]
else [FilePath
" " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
fqn FilePath -> FilePath -> FilePath
+++ FilePath
"x = ("FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
fqnFilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
")o;",
FilePath
" return " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
checkKids FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
";"]) [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++
[FilePath
" }",
FilePath
" return false;",
FilePath
"}"]
where
fqn :: FilePath
fqn = FilePath
packFilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
"."FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
fun
checkKids :: FilePath
checkKids = FilePath -> [FilePath] -> FilePath
forall a. [a] -> [[a]] -> [a]
intercalate FilePath
" && " ([FilePath] -> FilePath) -> [FilePath] -> FilePath
forall a b. (a -> b) -> a -> b
$ (IVar -> FilePath) -> [IVar] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map IVar -> FilePath
checkKid [IVar]
vs
checkKid :: IVar -> FilePath
checkKid IVar
iv = FilePath
"this." FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
v FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
".equals(x." FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
v FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
")"
where v :: FilePath
v = Doc -> FilePath
render (IVar -> Doc
iVarName IVar
iv)
prHashCode :: String -> String -> [IVar] -> String
prHashCode :: FilePath -> FilePath -> [IVar] -> FilePath
prHashCode FilePath
_ FilePath
_ [IVar]
vs =
[FilePath] -> FilePath
unlines ([FilePath] -> FilePath) -> [FilePath] -> FilePath
forall a b. (a -> b) -> a -> b
$ (FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath
" "FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++) [FilePath
"public int hashCode() {",
FilePath
" return " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ [IVar] -> FilePath
hashKids [IVar]
vs FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
";",
FilePath
"}"
]
where
aPrime :: FilePath
aPrime = FilePath
"37"
hashKids :: [IVar] -> FilePath
hashKids [] = FilePath
aPrime
hashKids (IVar
v:[IVar]
vs) = FilePath -> [IVar] -> FilePath
hashKids_ (IVar -> FilePath
hashKid IVar
v) [IVar]
vs
hashKids_ :: FilePath -> [IVar] -> FilePath
hashKids_ = (FilePath -> IVar -> FilePath) -> FilePath -> [IVar] -> FilePath
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\FilePath
r IVar
v -> FilePath
aPrime FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"*" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"(" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
r FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
")+" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ IVar -> FilePath
hashKid IVar
v)
hashKid :: IVar -> FilePath
hashKid IVar
iv = FilePath
"this." FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Doc -> FilePath
render (IVar -> Doc
iVarName IVar
iv) FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
".hashCode()"
prInstVars :: RecordPositions -> [IVar] -> Doc
prInstVars :: RecordPositions -> [IVar] -> Doc
prInstVars RecordPositions
rp [] = case RecordPositions
rp of
RecordPositions
RecordPositions -> Doc
"public int line_num, col_num, offset;"
RecordPositions
NoRecordPositions -> Doc
empty
prInstVars RecordPositions
rp vars :: [IVar]
vars@((FilePath
t,Int
_,FilePath
_):[IVar]
_) =
Doc
"public" Doc -> Doc -> Doc
<+> Doc
"final" Doc -> Doc -> Doc
<+> FilePath -> Doc
text FilePath
t Doc -> Doc -> Doc
<+> Doc
uniques Doc -> Doc -> Doc
P.<> Doc
";" Doc -> Doc -> Doc
$$ RecordPositions -> [IVar] -> Doc
prInstVars RecordPositions
rp [IVar]
vs'
where
(Doc
uniques, [IVar]
vs') = FilePath -> [IVar] -> (Doc, [IVar])
prUniques FilePath
t [IVar]
vars
prUniques :: String -> [IVar] -> (Doc, [IVar])
prUniques :: FilePath -> [IVar] -> (Doc, [IVar])
prUniques FilePath
t [IVar]
vs = ([IVar] -> [Int] -> Doc
prVars [IVar]
vs ((IVar -> Bool) -> [IVar] -> [Int]
forall a. (a -> Bool) -> [a] -> [Int]
findIndices (\(FilePath
y,Int
_,FilePath
_) -> FilePath
y FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
t) [IVar]
vs), FilePath -> [IVar] -> [IVar]
remType FilePath
t [IVar]
vs)
prVars :: [IVar] -> [Int] -> Doc
prVars [IVar]
vs = [Doc] -> Doc
hsep ([Doc] -> Doc) -> ([Int] -> [Doc]) -> [Int] -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc -> [Doc] -> [Doc]
punctuate Doc
comma ([Doc] -> [Doc]) -> ([Int] -> [Doc]) -> [Int] -> [Doc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Doc) -> [Int] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (IVar -> Doc
iVarName (IVar -> Doc) -> (Int -> IVar) -> Int -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([IVar]
vs[IVar] -> Int -> IVar
forall a. [a] -> Int -> a
!!))
remType :: String -> [IVar] -> [IVar]
remType :: FilePath -> [IVar] -> [IVar]
remType FilePath
_ [] = []
remType FilePath
t ((FilePath
t2,Int
n,FilePath
nm):[IVar]
ts)
| FilePath
t FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
t2 = FilePath -> [IVar] -> [IVar]
remType FilePath
t [IVar]
ts
| Bool
otherwise = (FilePath
t2,Int
n,FilePath
nm) IVar -> [IVar] -> [IVar]
forall a. a -> [a] -> [a]
: FilePath -> [IVar] -> [IVar]
remType FilePath
t [IVar]
ts
iVarName :: IVar -> Doc
iVarName :: IVar -> Doc
iVarName (FilePath
_,Int
n,FilePath
nm) = FilePath -> Doc
text (FilePath -> FilePath
varName FilePath
nm) Doc -> Doc -> Doc
P.<> FilePath -> Doc
text (Int -> FilePath
showNum Int
n)
prConstructor :: String -> [UserDef] -> [IVar] -> [Cat] -> Doc
prConstructor :: FilePath -> [FilePath] -> [IVar] -> [Cat] -> Doc
prConstructor FilePath
c [FilePath]
u [IVar]
vs [Cat]
cats =
Doc
"public" Doc -> Doc -> Doc
<+> FilePath -> Doc
text FilePath
c Doc -> Doc -> Doc
P.<> Doc -> Doc
parens ([FilePath] -> [FilePath] -> Doc
interleave [FilePath]
types [FilePath]
params)
Doc -> Doc -> Doc
<+> Doc
"{" Doc -> Doc -> Doc
<+> FilePath -> Doc
text ([IVar] -> [FilePath] -> FilePath
prAssigns [IVar]
vs [FilePath]
params) Doc -> Doc -> Doc
P.<> Doc
"}"
where
([FilePath]
types, [FilePath]
params) = [(FilePath, FilePath)] -> ([FilePath], [FilePath])
forall a b. [(a, b)] -> ([a], [b])
unzip ([Cat] -> [FilePath] -> Int -> Int -> [(FilePath, FilePath)]
prParams [Cat]
cats [FilePath]
u ([Cat] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Cat]
cats) ([Cat] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Cat]
catsInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1))
interleave :: [FilePath] -> [FilePath] -> Doc
interleave [FilePath]
xs [FilePath]
ys = [Doc] -> Doc
hsep ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ Doc -> [Doc] -> [Doc]
punctuate Doc
"," ([Doc] -> [Doc]) -> [Doc] -> [Doc]
forall a b. (a -> b) -> a -> b
$ (FilePath -> FilePath -> Doc) -> [FilePath] -> [FilePath] -> [Doc]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (Doc -> Doc -> Doc
(<+>) (Doc -> Doc -> Doc)
-> (FilePath -> Doc) -> FilePath -> FilePath -> Doc
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` FilePath -> Doc
text) [FilePath]
xs [FilePath]
ys
prParams :: [Cat] -> [UserDef] -> Int -> Int -> [(String,String)]
prParams :: [Cat] -> [FilePath] -> Int -> Int -> [(FilePath, FilePath)]
prParams [Cat]
cs [FilePath]
user Int
n Int
m = (Cat -> Int -> (FilePath, FilePath))
-> [Cat] -> [Int] -> [(FilePath, FilePath)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Cat -> Int -> (FilePath, FilePath)
forall a. Show a => Cat -> a -> (FilePath, FilePath)
pr [Cat]
cs [Int
mInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
n, Int
mInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1 ..]
where pr :: Cat -> a -> (FilePath, FilePath)
pr Cat
c a
k = (FilePath -> [FilePath] -> FilePath -> FilePath
typename FilePath
"" [FilePath]
user (Cat -> FilePath
identCat Cat
c), Char
'p' Char -> FilePath -> FilePath
forall a. a -> [a] -> [a]
: a -> FilePath
forall a. Show a => a -> FilePath
show a
k)
prAssigns :: [IVar] -> [String] -> String
prAssigns :: [IVar] -> [FilePath] -> FilePath
prAssigns [] [FilePath]
_ = []
prAssigns [IVar]
_ [] = []
prAssigns ((FilePath
t,Int
n,FilePath
nm):[IVar]
vs) (FilePath
p:[FilePath]
ps) =
if Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 then
case (IVar -> Bool) -> [IVar] -> [Int]
forall a. (a -> Bool) -> [a] -> [Int]
findIndices (\IVar
x -> case IVar
x of (FilePath
l,Int
_,FilePath
_) -> FilePath
l FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
t) [IVar]
vs of
[] -> FilePath -> FilePath
varName FilePath
nm FilePath -> FilePath -> FilePath
+++ FilePath
"=" FilePath -> FilePath -> FilePath
+++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
";" FilePath -> FilePath -> FilePath
+++ [IVar] -> [FilePath] -> FilePath
prAssigns [IVar]
vs [FilePath]
ps
[Int]
_ -> FilePath -> FilePath
varName FilePath
nm FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Int -> FilePath
showNum Int
n FilePath -> FilePath -> FilePath
+++ FilePath
"=" FilePath -> FilePath -> FilePath
+++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
";" FilePath -> FilePath -> FilePath
+++ [IVar] -> [FilePath] -> FilePath
prAssigns [IVar]
vs [FilePath]
ps
else FilePath -> FilePath
varName FilePath
nm FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Int -> FilePath
showNum Int
n FilePath -> FilePath -> FilePath
+++ FilePath
"=" FilePath -> FilePath -> FilePath
+++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
";" FilePath -> FilePath -> FilePath
+++ [IVar] -> [FilePath] -> FilePath
prAssigns [IVar]
vs [FilePath]
ps
getVars :: [Cat] -> [UserDef] -> [IVar]
getVars :: [Cat] -> [FilePath] -> [IVar]
getVars [Cat]
cs [FilePath]
user = [IVar] -> [IVar]
forall a. [a] -> [a]
reverse ([IVar] -> [IVar]) -> [IVar] -> [IVar]
forall a b. (a -> b) -> a -> b
$ [IVar] -> [IVar]
forall c b a. (Eq c, Num b) => [(a, b, c)] -> [(a, b, c)]
singleToZero ([IVar] -> [IVar]) -> [IVar] -> [IVar]
forall a b. (a -> b) -> a -> b
$ ([IVar] -> FilePath -> [IVar]) -> [IVar] -> [FilePath] -> [IVar]
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl [IVar] -> FilePath -> [IVar]
forall b.
(Ord b, Num b) =>
[(FilePath, b, FilePath)] -> FilePath -> [(FilePath, b, FilePath)]
addVar [] ((Cat -> FilePath) -> [Cat] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map Cat -> FilePath
identCat [Cat]
cs)
where
addVar :: [(FilePath, b, FilePath)] -> FilePath -> [(FilePath, b, FilePath)]
addVar [(FilePath, b, FilePath)]
is FilePath
c = (FilePath
c', b
n, FilePath
c)(FilePath, b, FilePath)
-> [(FilePath, b, FilePath)] -> [(FilePath, b, FilePath)]
forall a. a -> [a] -> [a]
:[(FilePath, b, FilePath)]
is
where c' :: FilePath
c' = FilePath -> [FilePath] -> FilePath -> FilePath
typename FilePath
"" [FilePath]
user FilePath
c
n :: b
n = [b] -> b
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (b
1b -> [b] -> [b]
forall a. a -> [a] -> [a]
:[b
n'b -> b -> b
forall a. Num a => a -> a -> a
+b
1 | (FilePath
_,b
n',FilePath
c'') <- [(FilePath, b, FilePath)]
is, FilePath
c'' FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
c])
singleToZero :: [(a, b, c)] -> [(a, b, c)]
singleToZero [(a, b, c)]
is =
[ (a
t,b
n',c
nm)
| (a
t,b
n,c
nm) <- [(a, b, c)]
is
, let n' :: b
n' = if [c] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [c
n | (a
_,b
_,c
n) <- [(a, b, c)]
is, c
n c -> c -> Bool
forall a. Eq a => a -> a -> Bool
== c
nm] Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 then b
0 else b
n
]
varName :: String
-> String
varName :: FilePath -> FilePath
varName FilePath
c = (Char -> Char) -> FilePath -> FilePath
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower FilePath
c FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"_"
typename
:: String
-> [UserDef]
-> String
-> String
typename :: FilePath -> [FilePath] -> FilePath -> FilePath
typename FilePath
q [FilePath]
user FilePath
t
| FilePath
t FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
"Ident" = FilePath
"String"
| FilePath
t FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
"Char" = FilePath
"Character"
| FilePath
t FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
"Double" = FilePath
"Double"
| FilePath
t FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
"Integer" = FilePath
"Integer"
| FilePath
t FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
"String" = FilePath
"String"
| FilePath
t FilePath -> [FilePath] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FilePath]
user = FilePath
"String"
| FilePath -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null FilePath
q = FilePath
t
| Bool
otherwise = FilePath
q FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"." FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
t
cat2JavaType :: [UserDef] -> Cat -> String
cat2JavaType :: [FilePath] -> Cat -> FilePath
cat2JavaType [FilePath]
user = Cat -> FilePath
loop
where
loop :: Cat -> FilePath
loop = \case
ListCat Cat
c -> FilePath
"List" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Cat -> FilePath
loop Cat
c
Cat
c -> FilePath -> [FilePath] -> FilePath -> FilePath
typename FilePath
"" [FilePath]
user (FilePath -> FilePath) -> FilePath -> FilePath
forall a b. (a -> b) -> a -> b
$ Cat -> FilePath
identCat (Cat -> FilePath) -> Cat -> FilePath
forall a b. (a -> b) -> a -> b
$ Cat -> Cat
normCat Cat
c
cat2JavaTypeTopList :: [UserDef] -> Cat -> String
cat2JavaTypeTopList :: [FilePath] -> Cat -> FilePath
cat2JavaTypeTopList [FilePath]
user = \case
ListCat Cat
c -> FilePath
"java.util.LinkedList<" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ [FilePath] -> Cat -> FilePath
cat2JavaType [FilePath]
user Cat
c FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
">"
Cat
c -> [FilePath] -> Cat -> FilePath
cat2JavaType [FilePath]
user Cat
c