1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
module GenConvertST
( genConvInstances
)
where
import AbstractCurry.Types hiding ( QName )
import FlatCurry.Types hiding ( Visibility(..) )
import List ( nub )
import Data.FiniteMap
import State
import StateMonad
import Utilities
import Translate
import Lookup
genConvInstances :: Monad m => OptState m ()
genConvInstances = do
ftys <- gets funcTypes
let qns = nub $ concatMap compareTypes ftys
let lookupT (q1, q2) = do
td1 <- lookupTypeDecl q1
td2 <- lookupCTypeDecl q2
case td2 of
Prelude.Left td -> return (td1, translTypeDecl td)
Prelude.Right ctd -> return (td1, ctd)
tds <- mapM lookupT qns
mapM_ (uncurry genConv) tds
return ()
genConv :: Monad m => TypeDecl -> CTypeDecl -> OptState m ()
genConv t1 t2 = case (t1, t2) of
(Type qn1 _ _ _, CType qn2 _ _ _ _) ->
if qn1 == qn2 then genBasic qn1 else genComplex t1 t2
_ -> return ()
genBasic :: Monad m => QName -> OptState m ()
genBasic qn@(m, n) = do
let qn' s = (m, s ++ "_" ++ n ++ "_" ++ n)
typ f1 f2 =
CQualType (CContext []) (CFuncType (f1 $ CTCons qn) (f2 $ CTCons qn))
rule = CRule [] (CSimpleRhs (CSymbol ("Prelude", "id")) [])
func qname = CFunc (qn' qname) 1 Public (typ id id) [rule]
toSTRule <- genRuleToST 0 (qn' "toValST")
fromSTRule <- genRuleFromST 0 (qn' "fromValST")
let func' f1 f2 qname r = CFunc (qn' qname) 1 Public (typ f1 f2) [r]
funcs =
[ func "toValST"
, func "fromValST"
, func' id addST "toST" toSTRule
, func' addST addValues "fromST" fromSTRule
]
modify $ addCurryFDs funcs
genComplex :: Monad m => TypeDecl -> CTypeDecl -> OptState m ()
genComplex t1 t2 = case (t1, t2) of
(Type qn1 _ tvs1 cds1, CType qn2 _ _ cds2 _) -> do
let vcnt = length tvs1
valFunc = genFunc vcnt cds1 cds2 (qn1, qn2)
toValSTFunc <- valFunc ToValST
fromValSTFunc <- valFunc FromValST
toSTFunc <- valFunc ToST
fromSTFunc <- valFunc FromST
modify $ addCurryFDs [toValSTFunc, fromValSTFunc, toSTFunc, fromSTFunc]
_ -> return ()
data STFunction = ToValST | FromValST | ToST | FromST
genFunc
:: Monad m
=> Int
-> [ConsDecl]
-> [CConsDecl]
-> (QName, QName)
-> STFunction
-> OptState m CFuncDecl
genFunc vcnt cds1 cds2 (qn1@(m, n1), qn2@(_, n2)) stf =
let
qn' = genQName m n1 n2
eis = take vcnt evens
ois = take vcnt odds
funcType st cty1 cty2 cnstrs = CQualType
(CContext cnstrs)
(foldr CFuncType cty2 (argFuncTypes st ++ [cty1]))
argFuncTypes st = map (argFuncType st) eis
consType qn f is = f $ listToType qn (map (CTVar . translTVar) is)
argFuncType f i =
CFuncType (CTVar $ translTVar i) (f (CTVar . translTVar $ i + 1))
genRules f insts = mapM (uncurry $ f vcnt insts) (zip cds1 cds2)
funcDecl qn typ rules = CFunc qn (vcnt + 1) Public typ rules
in
case stf of
ToValST -> do
ftys <- gets funcTypes
rules <- genRules genRuleToValST (nub $ concatMap compareTypes ftys)
let typ = funcType addST (consType qn1 id eis) (consType qn2 id ois) []
return $ funcDecl (qn' "toValST") typ rules
FromValST -> do
ftys <- gets funcTypes
rules <- genRules genRuleFromValST
(map swap $ nub (concatMap compareTypes ftys))
let typ = funcType id (consType qn2 id eis) (consType qn1 id ois) []
return $ funcDecl (qn' "fromValST") typ rules
ToST -> do
rule <- genRuleToST vcnt (qn' "toValST")
let typ =
funcType addST (consType qn1 id eis) (consType qn2 addST ois) []
return $ funcDecl (qn' "toST") typ [rule]
FromST -> do
rule <- genRuleFromST vcnt (qn' "fromValST")
tSTMap <- gets typeSTMap
case lookupFM tSTMap qn2 of
Just oqn ->
let
typ = funcType id
(consType qn2 addST eis)
(consType oqn addValues ois)
cnstrs
cnstrs = map (\i -> (("ST", "NF"), CTVar $ translTVar i)) eis
in
return $ funcDecl (qn' "fromST") typ [rule]
Nothing ->
error $ "genFunc: Missing original data type for " ++ show qn2
genRuleToValST
:: Monad m
=> Int
-> [(QName, QName)]
-> ConsDecl
-> CConsDecl
-> OptState m CRule
genRuleToValST _ _ (FlatCurry.Types.Cons _ _ _ _) (CRecord _ _ _ _ _) =
notImplemented "genRuleToValSt" "Record types"
genRuleToValST tvars insts (FlatCurry.Types.Cons qn ar _ tys) (CCons _ _ cqn _ _)
= do
m <- gets currentModule
vs <- freshVars tvars
xs <- freshVars ar
let iargs = zip (nub $ concatMap typeVars tys) vs
txs = zip xs tys
rule = CRule (map CPVar vs ++ [CPComb qn (map CPVar xs)]) rhs
genRuleExp = genRuleToValSTExpr m iargs insts
rhs = CSimpleRhs (listToExpr cqn (map genRuleExp txs)) []
return rule
genRuleFromValST
:: Monad m
=> Int
-> [(QName, QName)]
-> ConsDecl
-> CConsDecl
-> OptState m CRule
genRuleFromValST _ _ (FlatCurry.Types.Cons _ _ _ _) (CRecord _ _ _ _ _) =
notImplemented "genRuleFromValST" "Record types"
genRuleFromValST tvars insts (FlatCurry.Types.Cons qn ar _ _) (CCons _ _ cqn _ ctys)
= do
m <- gets currentModule
vs <- freshVars tvars
xs <- freshVars ar
let iargs = zip (nub $ concatMap ctypeVars ctys) vs
txs = zip xs ctys
pat i = CPComb ("ST", "Val") [CPVar i]
rule = CRule (map CPVar vs ++ [CPComb cqn (map pat xs)]) rhs
genRuleExp = genRuleFromValSTExpr m iargs insts
rhs = CSimpleRhs (listToExpr qn (map genRuleExp txs)) []
return rule
genRuleToValSTExpr
:: String
-> [(TVarIndex, CTVarIName)]
-> [(QName, QName)]
-> (CTVarIName, TypeExpr)
-> CExpr
genRuleToValSTExpr m iargs insts (y, t) = CApply (genRuleExpr' t) (CVar y)
where
genRuleExpr' typ = case typ of
TVar i -> case lookup i iargs of
Just v -> CVar v
Nothing ->
error
$ "genRuleToValSTExpr: Missing instance argument for variable "
++ show i
FuncType _ _ ->
notImplemented "genRuleToValSTExpr" "Higher-order functions"
TCons qname@(_, n1) ts -> case lookup qname insts of
Just (_, n2) ->
let args = map genRuleExpr' ts
qname' = genQName m n1 n2 "toST"
in listToExpr qname' args
Nothing ->
error $ "genRuleToValSTExpr: Missing instance for " ++ show qname
ForallType _ ty -> genRuleExpr' ty
genRuleFromValSTExpr
:: String
-> [(CTVarIName, CTVarIName)]
-> [(QName, QName)]
-> (CTVarIName, CTypeExpr)
-> CExpr
genRuleFromValSTExpr m iargs insts (y, t) = CApply (genRuleExpr' t) (CVar y)
where
genRuleExpr' typ = case typ of
CTVar i -> case lookup i iargs of
Just v -> CVar v
Nothing ->
error
$ "genRuleFromValSTExpr: Missing instance argument for variable "
++ show i
CFuncType _ _ ->
notImplemented "genRuleFromValSTExpr" "Higher-order functions"
CTCons qname@(_, n1) -> case lookup qname insts of
Just (_, n2) -> CSymbol $ genQName m n2 n1 "fromValST"
Nothing ->
error $ "genRuleFromValSTExpr: Missing instance for " ++ show qname
CTApply (CTCons ("ST", "ST")) x -> genRuleExpr' x
CTApply f x -> CApply (genRuleExpr' f) (genRuleExpr' x)
genRuleToST :: Monad m => Int -> QName -> OptState m CRule
genRuleToST tvars qn = do
vs <- freshVars tvars
let rule = CRule (map CPVar vs) rhs
uneval = CApply (CSymbol ("Prelude", ".")) (CSymbol ("ST", "Uneval"))
exp = CApply uneval (listToExpr qn (map CVar vs))
rhs = CSimpleRhs exp []
return rule
genRuleFromST :: Monad m => Int -> QName -> OptState m CRule
genRuleFromST tvars qn = do
vs <- freshVars tvars
let rule = CRule (map CPVar vs) rhs
mape = listToExpr ("Prelude", "map") [listToExpr qn (map CVar vs)]
exp = listToExpr ("Prelude", ".") [mape, (CSymbol ("ST", "stValues"))]
rhs = CSimpleRhs exp []
return rule
|