summaryrefslogtreecommitdiff
path: root/src/compiler/GF/Compile
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/GF/Compile')
-rw-r--r--src/compiler/GF/Compile/ConcreteToHaskell.hs210
1 files changed, 71 insertions, 139 deletions
diff --git a/src/compiler/GF/Compile/ConcreteToHaskell.hs b/src/compiler/GF/Compile/ConcreteToHaskell.hs
index 0b55a959d..3dc71b3f5 100644
--- a/src/compiler/GF/Compile/ConcreteToHaskell.hs
+++ b/src/compiler/GF/Compile/ConcreteToHaskell.hs
@@ -17,6 +17,7 @@ import GF.Compile.Compute.Value(Predefined(..))
import GF.Infra.Ident(Ident,identS,prefixIdent) --,moduleNameS
import GF.Infra.Option
import GF.Compile.Compute.ConcreteNew(normalForm,resourceValues)
+import GF.Haskell
import Debug.Trace
-- | Generate Haskell code for the all concrete syntaxes associated with
@@ -34,52 +35,55 @@ concretes2haskell opts absname gr =
-- @-haskell=noprefix@ and @-haskell=variants@.
concrete2haskell opts gr cenv absname cnc modinfo =
renderStyle style{lineLength=80,ribbonsPerLine=1} $
- haskPreamble va absname cnc $$ "" $$
- "--- Parameter types ---" $$
- vcat (neededParamTypes S.empty (params defs)) $$ "" $$
- "--- Type signatures for linearization functions ---" $$
- vcat (map signature (S.toList allcats)) $$ "" $$
- "--- Linearization functions for empty categories ---" $$
- vcat emptydefs $$ "" $$
- "--- Linearization types and linearization functions ---" $$
- vcat (map ppDef defs) $$ "" $$
- "--- Type classes for projection functions ---" $$
- vcat (map labelClass (S.toList labels)) $$ "" $$
- "--- Record types ---" $$
- vcat (map recordType recs)
+ haskPreamble va absname cnc $$ vcat (
+ nl:Comment "--- Parameter types ---":
+ neededParamTypes S.empty (params defs) ++
+ nl:Comment "--- Type signatures for linearization functions ---":
+ map signature (S.toList allcats)++
+ nl:Comment "--- Linearization functions for empty categories ---":
+ emptydefs ++
+ nl:Comment "--- Linearization types and linearization functions ---":
+ map ppDef defs ++
+ nl:Comment "--- Type classes for projection functions ---":
+ map labelClass (S.toList labels) ++
+ nl:Comment "--- Record types ---":
+ concatMap recordType recs)
where
+ nl = Comment ""
labels = S.difference (S.unions (map S.fromList recs)) common_labels
recs = S.toList (S.difference (records rhss) common_records)
common_records = S.fromList [[label_s]]
common_labels = S.fromList [label_s]
label_s = ident2label (identS "s")
- rhss = map (snd.snd) defs
- defs = sortBy (compare `on` fst) .
+ rhss = map (either snd (snd.snd)) defs
+ defs = sortBy (compare `on` either (const Nothing) (Just . fst)) .
concatMap (toHaskell gId gr absname cenv) .
M.toList $
jments modinfo
-- signature c = "lin"<>c<+>"::"<+>"A."<>gId c<+>"->"<+>"Lin"<>c
-- signature c = "--lin"<>c<+>":: (Applicative f,Monad f) =>"<+>"A."<>gId c<+>"->"<+>"f Lin"<>c
- signature c = "lin"<>c<+>"::"<+>Fun abs (pure lin)
+ signature c = TypeSig lf (Fun abs (pure lin))
where
abs = tcon0 (prefixIdent "A." (gId c))
- lin = tcon0 (prefixIdent "Lin" c)
+ lin = tcon0 lc
+ lf = prefixIdent "lin" c
+ lc = prefixIdent "Lin" c
emptydefs = map emptydef (S.toList emptyCats)
- emptydef c = "lin"<>c<+>"_"<+>"="<+>"undefined"
+ emptydef c = Eqn (prefixIdent "lin" c,[WildP]) (Const "undefined")
emptyCats = allcats `S.difference` cats
- cats = S.fromList [c|(Just c,_)<-defs]
+ cats = S.fromList [c|Right (c,_)<-defs]
allcats = S.fromList [c|((_,c),AbsCat (Just _))<-allOrigInfos gr absname]
-
+
params = S.toList . S.unions . map params1
- params1 (Nothing,(_,rhs)) = paramTypes gr rhs
- params1 (_,(_,rhs)) = tableTypes gr [rhs]
+ params1 (Left (_,rhs)) = paramTypes gr rhs
+ params1 (Right (_,(_,rhs))) = tableTypes gr [rhs]
- ppDef (Nothing,(lhs,rhs)) = hang (lhs<+>"=") 2 (convType va gId rhs)
- ppDef (_,(lhs,rhs)) = hang (lhs<+>"=") 2 (convert va gId gr rhs)
+ ppDef (Left (lhs,rhs)) = lhs (convType va gId rhs)
+ ppDef (Right (_,(lhs,rhs))) = lhs (convert va gId gr rhs)
gId :: Ident -> Ident
gId = if haskellOption opts HaskellNoPrefix then id else prefixIdent "G"
@@ -91,7 +95,7 @@ concrete2haskell opts gr cenv absname cnc modinfo =
if q `S.member` have
then neededParamTypes have qs
else let ((got,need),def) = paramType va gId gr q
- in def:neededParamTypes (S.union got have) (S.toList need++qs)
+ in def++neededParamTypes (S.union got have) (S.toList need++qs)
haskPreamble :: Bool -> ModuleName -> ModuleName -> Doc
haskPreamble va absname cncname =
@@ -116,10 +120,10 @@ haskPreamble va absname cncname =
toHaskell gId gr absname cenv (name,jment) =
case jment of
CncCat (Just (L loc typ)) _ _ pprn _ ->
- [(Nothing,("type"<+>"Lin"<>name,nf loc typ))]
+ [Left (tsyn0 (prefixIdent "Lin" name),nf loc typ)]
CncFun (Just r@(cat,ctx,lincat)) (Just (L loc def)) pprn _ ->
-- trace (render (name<+>hcat[parens (x<>"::"<>t)|(_,x,t)<-ctx]<+>"::"<+>cat)) $
- [(Just cat,("lin"<>cat<+>lhs,coerce [] lincat rhs))]
+ [Right (cat,(Eqn (prefixIdent "lin" cat,lhs),coerce [] lincat rhs))]
where
Ok abstype = lookupFunType gr absname name
(absctx,abscat,absargs) = typeForm abstype
@@ -128,9 +132,8 @@ toHaskell gId gr absname cenv (name,jment) =
nf loc (mkAbs params (mkApp def (map Vr args)))
params = [(b,prefixIdent "g" x)|(b,x,_)<-ctx]
args = map snd params
- abs_args = map ("abs_"<>) args
- lhs = if null args then pp (aId name)
- else parens (aId name<+>hsep abs_args)
+ abs_args = map (prefixIdent "abs_") args
+ lhs = [ConP (aId name) (map VarP abs_args)]
rhs = foldr letlin e' (zip args absctx)
letlin (a,(_,_,at)) =
Let (a,(Just (con ("Lin"++render at)),(App (con ("lin"++render at)) (con ("abs_"++render a)))))
@@ -349,64 +352,72 @@ convType va gId = ppT
fields = map (ppT.snd) . sort . filter (not.isLockLabel.fst)
-proj l = con ("proj_"++render l)
+proj = con . proj'
+proj' l = "proj_"++render l
rcon = con . rcon_name
rcon' = identS . rcon_name
rcon_name ls = "R"++concat (sort ['_':render l|l<-ls,not (isLockLabel l)])
-to_rcon = con . ("to_"++) . rcon_name
+to_rcon = con . to_rcon'
+to_rcon' = ("to_"++) . rcon_name
recordType ls =
- "data"<+>app<+>"="<+>app <+> "deriving (Eq,Ord,Show)" $$
- enumAllInstance $$
- vcat (zipWith projection vs ls) $$
- hang (to_rcon ls<+>"r"<+>"=") 4
- (cn<+>fsep [parens (proj l<+>"r")|l<-ls]) $$ ""
+ Data lhs [app] ["Eq","Ord","Show"]:
+ enumAllInstance:
+ zipWith projection vs ls ++
+ [Eqn (identS (to_rcon' ls),[VarP r])
+ (foldl Ap (Var cn) [Var (identS (proj' l)) `Ap` Var r|l<-ls])]
where
- cn = rcon ls
- cn' = rcon' ls
+ r = identS "r"
+ cn = rcon' ls
-- Not all record labels are syntactically correct as type variables in Haskell
-- app = cn<+>ls
- app = cn<+>hsep vs -- don't reuse record labels
- vs = ["t"<>i|i<-[1..n]]
+ lhs = ConAp cn vs -- don't reuse record labels
+ app = fmap TId lhs
+ tapp = foldl TAp (TId cn) (map TId vs)
+ vs = [identS ('t':show i)|i<-[1..n]]
n = length ls
- projection v l =
- hang ("instance"<+>"Has_"<>l<+>parens app<+>v<+>"where") 4
- (proj l<+>parens app<+>"="<+>v)
+ projection v l = Instance [] (TId name `TAp` tapp `TAp` TId v)
+ [((prj,[papp]),Var v)]
+ where
+ name = identS ("Has_"++render l)
+ prj = identS (proj' l)
+ papp = ConP cn (map VarP vs)
enumAllInstance =
- hang ("instance"<+>ctx<+>"EnumAll"<+>parens app<+>"where") 4
- (hang ("enumAll"<+>"=") 4 (enumCon cn' n))
+ Instance ctx (tEnumAll `TAp` tapp)[(lhs0 "enumAll",enumCon cn n)]
where
- ctx = if n==0
- then empty
- else parens (fsep (punctuate "," ["EnumAll"<+>v|v<-vs]))<+>"=>"
+ ctx = [tEnumAll `TAp` TId v|v<-vs]
+ tEnumAll = TId (identS "EnumAll")
labelClass l =
- hang ("class"<+>"Has_"<>l<+>"r"<+>"a"<+>"| r -> a"<+>"where") 4
- (proj l<+>"::"<+>"r -> a")
+ Class [] (ConAp name [r,a]) [([r],[a])]
+ [(identS (proj' l),TId r `Fun` TId a)]
+ where
+ name = identS ("Has_"++render l)
+ r = identS "r"
+ a = identS "a"
paramType va gId gr q@(_,n) =
case lookupOrigInfo gr q of
Ok (m,ResParam (Just (L _ ps)) _)
{- - | m/=cPredef && m/=moduleNameS "Prelude"-} ->
((S.singleton (m,n),argTypes ps),
- hang ("data"<+>gId (qual m n)<+>"=") 7
- (sep [fsep (punctuate " |" (map (param m) ps)),
- pp "deriving (Eq,Ord,Show)"]) $$
- hang ("instance EnumAll"<+>gId (qual m n)<+>"where") 4
- ("enumAll"<+>"="<+>foldr1 plusplus (map (enumParam m) ps))
+ [Data (conap0 name) (map (param m) ps)["Eq","Ord","Show"],
+ Instance [] (TId (identS "EnumAll") `TAp` TId name)
+ [(lhs0 "enumAll",foldr1 plusplus (map (enumParam m) ps))]]
)
+ where name = gId (qual m n)
Ok (m,ResOper _ (Just (L _ t)))
| m==cPredef && n==cInts ->
((S.singleton (m,n),S.empty),
- "type"<+>gId (qual m n)<+>"n = Int")
+ [Type (ConAp (gId (qual m n)) [identS "n"]) (TId (identS "Int"))])
| otherwise ->
((S.singleton (m,n),paramTypes gr t),
- "type"<+>gId (qual m n)<+>"="<+>convType va gId t)
- _ -> ((S.empty,S.empty),empty)
+ [Type (conap0 (gId (qual m n))) (convType va gId t)])
+ _ -> ((S.empty,S.empty),[])
where
- param m (n,ctx) = tcon (gId (qual m n)) [convType va gId t|(_,_,t)<-ctx]
+ param m (n,ctx) = ConAp (gId (qual m n)) [convType va gId t|(_,_,t)<-ctx]
argTypes = S.unions . map argTypes1
argTypes1 (n,ctx) = S.unions [paramTypes gr t|(_,_,t)<-ctx]
@@ -422,82 +433,3 @@ enumCon name arity =
qual :: ModuleName -> Ident -> Ident
qual m = prefixIdent (render m++"_")
-
---------------------------------------------------------------------------------
--- ** A Haskell subset
-
-data Ty = TId Ident | TAp Ty Ty | Fun Ty Ty | ListT Ty
-
-data Exp = Var Ident | Const String | Ap Exp Exp | Op Exp String Exp
- | List [Exp] | Pair Exp Exp
- | Lets [(Ident,Exp)] Exp | LambdaCase [(Pat,Exp)]
-
-data Pat = WildP | VarP Ident | Lit String | ConP Ident [Pat] | AsP Ident Pat
-
-tvar = TId
-tcon0 = TId
-tcon c = foldl TAp (TId c)
-
-let1 x xe e = Lets [(x,xe)] e
-single x = List [x]
-
-plusplus (List ts1) (List ts2) = List (ts1++ts2)
-plusplus (List [t]) t2 = Op t ":" t2
-plusplus t1 t2 = Op t1 "++" t2
-
-instance Pretty Ty where
- pp = ppT
- where
- ppT t = case flatFun t of t:ts -> sep (ppB t:["->"<+>ppB t|t<-ts])
- ppB t = case flatTAp t of t:ts -> ppA t<+>sep (map ppA ts)
-
- ppA t =
- case t of
- TId c -> pp c
- ListT t -> brackets t
- _ -> parens t
-
- flatFun (Fun t1 t2) = t1:flatFun t2 -- right associative
- flatFun t = [t]
-
- flatTAp (TAp t1 t2) = flatTAp t1++[t2] -- left associative
- flatTAp t = [t]
-
-instance Pretty Exp where
- pp = ppT
- where
- ppT e =
- case e of
- Op e1 op e2 -> hang (ppB e1<+>op) 2 (ppB e2)
- Lets bs e -> sep ["let"<+>vcat [hang (x<+>"=") 2 xe|(x,xe)<-bs],
- "in" <+>e]
- LambdaCase alts -> hang "\\case" 4 (vcat [p<+>"->"<+>e|(p,e)<-alts])
- _ -> ppB e
-
- ppB e = case flatAp e of f:as -> hang (ppA f) 2 (sep (map ppA as))
-
- ppA e =
- case e of
- Var x -> pp x
- Const n -> pp n
- Pair e1 e2 -> parens (e1<>","<>e2)
- List es -> brackets (fsep (punctuate "," es))
- _ -> parens e
-
- flatAp (Ap t1 t2) = flatAp t1++[t2] -- left associative
- flatAp t = [t]
-
-instance Pretty Pat where
- pp = ppP
- where
- ppP p =
- case p of
- ConP c ps -> c<+>fsep (map ppPA ps)
- _ -> ppPA p
- ppPA p =
- case p of
- WildP -> pp "_"
- VarP x -> pp x
- Lit s -> pp s
- AsP x p -> x<>"@"<>parens p
- _ -> parens p