module GF.Compile.PGFtoJava (grammar2java) where

import PGF
import Data.Maybe(maybe)
import Data.List(intercalate)
import GF.Infra.Option

-- | the main function
grammar2java :: Options
                -> String  -- ^ Module name.
                -> PGF
                -> String
grammar2java :: Options -> String -> PGF -> String
grammar2java Options
opts String
name PGF
gr = [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$  
  String -> [String]
javaPreamble String
name [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
methods [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
javaEnding
  where
    methods :: [String]
methods = [PGF -> CId -> String
javaMethod PGF
gr CId
fun | CId
fun <- PGF -> [CId]
functions PGF
gr]

javaPreamble :: String -> [String]
javaPreamble String
name =
 [
  String
"import org.grammaticalframework.pgf.*;",
  String
"",
  String
"public class " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" {",
  String
""
 ]
 
javaMethod :: PGF -> CId -> String
javaMethod PGF
gr CId
fun =
  String
"  public static Expr "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
nameString -> String -> String
forall a. [a] -> [a] -> [a]
++String
"("String -> String -> String
forall a. [a] -> [a] -> [a]
++String
arg_declsString -> String -> String
forall a. [a] -> [a] -> [a]
++String
") { return new Expr("String -> String -> String
forall a. [a] -> [a] -> [a]
++String -> String
forall a. Show a => a -> String
show String
nameString -> String -> String
forall a. [a] -> [a] -> [a]
++String
argsString -> String -> String
forall a. [a] -> [a] -> [a]
++String
"); }"
  where
    name :: String
name  = CId -> String
showCId CId
fun
    arity :: Int
arity = Int -> (Type -> Int) -> Maybe Type -> Int
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int
0 Type -> Int
getArrity (PGF -> CId -> Maybe Type
functionType PGF
gr CId
fun)
    vars :: [String]
vars  = [Char
'e'Char -> String -> String
forall a. a -> [a] -> [a]
:Int -> String
forall a. Show a => a -> String
show Int
i | Int
i <- [Int
1..Int
arity]]
    
    arg_decls :: String
arg_decls = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"," [String
"Expr "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
v | String
v <- [String]
vars]
    args :: String
args      = if [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
vars then String
",new Expr[] {}" else String
","String -> String -> String
forall a. [a] -> [a] -> [a]
++String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"," [String]
vars

    getArrity :: Type -> Int
getArrity Type
ty = [Hypo] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Hypo]
hypos
      where
        ([Hypo]
hypos,CId
_,[Expr]
_) = Type -> ([Hypo], CId, [Expr])
unType Type
ty

javaEnding :: [String]
javaEnding =
 [
  String
"",
  String
"}"
 ]