-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathGenSML.hs
544 lines (503 loc) · 15.2 KB
/
GenSML.hs
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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
module Gibbon.L1.GenSML where
import Gibbon.L1.Syntax
import Gibbon.Common
import Text.PrettyPrint hiding ((<>))
import Data.Maybe
import Control.Monad
import Data.Map hiding (foldr, fold, null, empty)
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified Safe as Sf
import Data.Foldable hiding ( toList )
import Data.Graph
import Data.Tree ( flatten )
ppExt :: E1Ext () Ty1 -> Doc
ppExt ext0 = case ext0 of
BenchE _var _uts _pes _b -> error "BenchE"
AddFixed _var _n -> error "AddFixed"
StartOfPkdCursor _var -> error "StartOfPkdCursor"
ppE :: Exp1 -> Doc
ppE e0 = case e0 of
VarE var -> ppVar var
LitE n -> int n
CharE c -> char c
FloatE x -> double x
LitSymE var -> doubleQuotes $ ppVar var
AppE var _ pes -> ppAp (ppVar var) pes
PrimAppE pr pes -> ppPrim pr pes
LetE (v, _, _, e) pe' ->
hsep
[ "\n let val", ppVar v, "="
, ppE e, "in"
, ppE pe', "end"
]
IfE pe' pe2 pe3 ->
("\n " <>) $ parens $ hsep
[ "if", ppE pe'
, "then", ppE pe2
, "\n else", ppE pe3
]
MkProdE pes -> parens $ interleave comma $ ppE <$> pes
ProjE 0 pe' -> parens $ hsep
[ "case", ppE pe', "of"
, "(t0, _) => t0"
]
ProjE 1 pe' -> parens $ hsep
[ "case", ppE pe', "of"
, "(_, t1) => t1"
]
ProjE n pe' -> parens $ hsep [hcat ["#", int $ succ n], ppE pe']
CaseE pe' x0 ->
parens $ hsep
[ hsep ["case", ppE pe', "of"]
, interleave "\n |" ((\(dc, vs, e) -> hsep
[ text dc
, case vs of
[] -> mempty
_ -> parens $ interleave comma $ ppVar . fst <$> vs
, "=>", ppE e
]) <$> x0)
]
DataConE _ty0 s [] -> text s
DataConE _ty0 s pes ->
parens $ hsep
[ text s
, parens $ interleave comma $ ppE <$> pes
]
TimeIt _pe' _ty0 _b -> _
WithArenaE _var _pe' -> error "WithArenaE"
SpawnE _var _ty0s _pes -> error "SpawnE"
SyncE -> error "SyncE"
MapE _x0 _pe' -> error "MapE"
FoldE _x0 _x1 _pe' -> error "FoldE"
Ext ee -> ppExt ee
ppCurried :: Doc -> [Exp1] -> Doc
ppCurried var pes = parens $ hsep $ var : (ppE <$> pes)
ppAp :: Doc -> [Exp1] -> Doc
ppAp var pes =
parens $ var <> case pes of
[] -> empty -- don't confuse with application to unit (1 arg)
[x] -> space <> ppE x
_ -> parens $ interleave "," $ ppE <$> pes
ppVar :: Var -> Doc
ppVar = text . getVar
getVar :: Var -> String
getVar (Var s) = case unintern s of
"val" -> "val_"
"as" -> "as_"
"open" -> "open_"
"rec" -> "rec_"
"fun" -> "fun_"
"end" -> "end_"
'_' : z -> "internal_" ++ z
z -> z
interleave :: Doc -> [Doc] -> Doc
interleave sepr lst = case lst of
[] -> mempty
d : ds -> (d <+>) $ fold $ (sepr <+>) <$> ds
binary :: String -> [Exp1] -> Doc
binary opSym pes =
parens $ hsep [l, text opSym, r]
where
(l, r) = extractBinary opSym pes
extractBinary :: String -> [Exp1] -> (Doc, Doc)
extractBinary opSym pes = case ppE <$> pes of
[l, r] -> (l, r)
es -> error $ fold
[ "L0 error: (", opSym, ") is provided "
, show $ length es, " arguments"
]
extractUnary :: String -> [Exp1] -> Doc
extractUnary opSym pes = case ppE <$> pes of
[x] -> x
es -> error $ fold
[ "L0 error: (", opSym, ") is provided "
, show $ length es, " arguments"
]
ppFail :: String -> Doc
ppFail s = hsep
[ "raise"
, parens $ hsep ["Fail", doubleQuotes $ text s]
]
ppPrim :: Prim Ty1 -> [Exp1] -> Doc
ppPrim pr pes = case pr of
AddP -> binary "+" pes
SubP -> binary "-" pes
MulP -> binary "*" pes
DivP -> binary "div" pes
ModP -> binary "mod" pes
ExpP -> binary "**" pes
RandP -> ppCurried "MltonRandom.rand()" pes
EqIntP -> binary "=" pes
LtP -> binary "<" pes
GtP -> binary ">" pes
LtEqP -> binary "<=" pes
GtEqP -> binary ">=" pes
FAddP -> binary "+" pes
FSubP -> binary "-" pes
FMulP -> binary "*" pes
FDivP -> binary "/" pes
FExpP ->
parens $ hsep
[ "Math.pow"
, parens $ hcat [l, comma, r]
]
where
(l, r) = extractBinary "pow" pes
FRandP -> ppCurried "Random.randFloat" pes
EqFloatP -> binary "=" pes
EqCharP -> binary "=" pes
FLtP -> binary "<" pes
FGtP -> binary ">" pes
FLtEqP -> binary "<=" pes
FGtEqP -> binary ">=" pes
FSqrtP -> ppAp "Math.sqrt" pes
IntToFloatP -> ppAp "Real.fromInt" pes
FloatToIntP -> ppAp "Int.fromReal" pes
FTanP -> ppAp "Math.tan" pes
EqSymP -> binary "=" pes
EqBenchProgP _ -> error "GenSML: EqBenchProgP"
OrP -> binary "orelse" pes
AndP -> binary "andalso" pes
MkTrue -> "true"
MkFalse -> "false"
ErrorP s _ -> ppFail s
SizeParam -> int 1 -- ?
IsBig -> error "IsBig"
GetNumProcessors -> error "GetNumProcessors"
PrintInt -> printer "Int" $ ppE $ Sf.headErr pes
PrintChar -> printer "Char" $ ppE $ Sf.headErr pes
PrintFloat -> printer "Float" $ ppE $ Sf.headErr pes
PrintBool -> ppAp "(fn true => \"True\" | false => \"False\")" pes
PrintSym -> ppAp "print" pes
ReadInt -> error "ReadInt" -- Have every program read from stdin?
DictInsertP _ -> error "DictInsertP"
DictLookupP _ -> error "DictLookupP"
DictEmptyP _ -> error "DictEmptyP"
DictHasKeyP _ -> error "DictHasKeyP"
SymSetEmpty -> error "SymSetEmpty"
SymSetInsert -> error "SymSetInsert"
SymSetContains -> error "SymSetContains"
SymHashEmpty -> error "SymHashEmpty"
SymHashInsert -> error "SymHashInsert"
SymHashLookup -> error "SymHashLookup"
SymHashContains -> error "SymHashContains"
IntHashEmpty -> error "IntHashEmpty"
IntHashInsert -> error "IntHashInsert"
IntHashLookup -> error "IntHashLookup"
PDictAllocP _ty0 _ty0' -> error "PDictAllocP"
PDictInsertP _ty0 _ty0' -> error "PDictInsertP"
PDictLookupP _ty0 _ty0' -> error "PDictLookupP"
PDictHasKeyP _ty0 _ty0' -> error "PDictHasKeyP"
PDictForkP _ty0 _ty0' -> error "PDictForkP"
PDictJoinP _ty0 _ty0' -> error "PDictJoinP"
LLAllocP _ty0 -> error "LLAllocP"
LLIsEmptyP _ty0 -> error "LLIsEmptyP" -- Implement these?
LLConsP _ty0 -> error "LLConsP"
LLHeadP _ty0 -> error "LLHeadP"
LLTailP _ty0 -> error "LLTailP"
LLFreeP _ty0 -> error "LLFreeP"
LLFree2P _ty0 -> error "LLFree2P"
LLCopyP _ty0 -> error "LLCopyP"
VAllocP _ty0 ->
ppAp "(fn internal__ => ArraySlice.full(Array.array(internal__, 0)))" pes
VFreeP _ty0 -> error "VFreeP"
VFree2P _ty0 -> error "VFree2P"
VLengthP _ty0 -> ppAp "ArraySlice.length" pes
VNthP _ty0 -> ppAp "ArraySlice.sub" pes
VSliceP _ty0 -> case pes of
[pe1, pe2, pe3] -> hcat
[ "ArraySlice.subslice"
, parens $ interleave comma
[ ppE pe3
, ppE pe1
, parens $ "SOME" <+> ppE pe2
]
]
_ -> _
InplaceVUpdateP _ty0 -> hsep
[ "let val _ ="
, ppAp "ArraySlice.update" pes
, "in", ppE $ Sf.headErr pes
, "end"
]
VConcatP _ty0 -> ppFail "VConcatP"
VSortP _ty0 -> ppFail "VSortP"
InplaceVSortP _ty0 -> ppCurried qsort pes
VMergeP _ty0 -> ppFail "VMergeP"
Write3dPpmFile _s -> error "Write3dPpmFile"
ReadPackedFile _m_s _s _m_var _ty0 -> error "ReadPackedFile"
WritePackedFile _s _ty0 -> error "WritePackedFile"
ReadArrayFile _ma _ty0 -> error "ReadArrayFile"
RequestEndOf -> error "RequestEndOf"
RequestSizeOf -> error "RequestSizeOf"
Gensym -> error "Gensym"
ppProgram :: Prog1 -> Doc
ppProgram prog = hcat
[ ppDDefs $ ddefs prog
, ppFunDefs $ fundefs prog
, ppMainExpr $ mainExp prog
, "\n"
]
ppFunDefs :: Map Var (FunDef Var Exp1) -> Doc
ppFunDefs funDefs =
foldMap ppBlock organize
where
ppBlock = either ppValDef ppFunRec
organize = sortDefs (elems funDefs) >>= separateDefs
separateDefs :: [FunDef Var Exp1] -> [Either (FunDef Var Exp1) [FunDef Var Exp1]]
separateDefs funDefs = case funDefs of
[] -> []
fd : fds -> case funArgs fd of
[] -> Left fd : separateDefs fds
_ -> case separateDefs fds of
[] -> [Right [fd]]
fds'@(Left _ : _) -> Right [fd] : fds'
Right fds' : fds'' -> Right (fd : fds') : fds''
ppValDef :: FunDef Var Exp1 -> Doc
ppValDef funDef =
hsep
[ "val"
, ppVar $ funName funDef
, "="
, ppE $ funBody funDef
] <> semi
ppFunRec :: [FunDef Var Exp1] -> Doc
ppFunRec fdefs =
reduceFunDefs "fun" (Sf.headErr fdefs) $
foldr (reduceFunDefs "and") ";\n" (Sf.tailErr fdefs)
reduceFunDefs :: Doc -> FunDef Var Exp1 -> Doc -> Doc
reduceFunDefs keyword funDef doc =
"\n" <> case funArgs funDef of
[] -> hsep
[ keyword
, ppVar $ funName funDef
, "="
, ppE $ funBody funDef
] <> doc
fargs -> hsep
[ keyword
, ppVar name
, parens $ interleave comma $ ppVar <$> fargs
, "="
, case name of
"print_check" -> parens mempty
"print_space" -> "print \" \""
"print_newline" -> "print \"\\n\""
_ -> ppE $ funBody funDef
] <> doc
where name = funName funDef
ppMainExpr :: Maybe (Exp1, Ty1) -> Doc
ppMainExpr opt = case opt of
Nothing -> mempty
Just (exp1, ty1) ->
"val _ = " <> printerTy1 ty1 (ppE exp1) <> semi
<> "\nval _ = print \"\\n\""
ppDDefs :: DDefs1 -> Doc
ppDDefs ddefs = case elems ddefs of
[] -> mempty
h : t -> hsep
[ "datatype"
, ppDDef h
, hcat $ ("\nand" <+>) . ppDDef <$> t
, ";\n"
]
ppDDef :: DDef1 -> Doc
ppDDef ddef = hsep
[ hsep $ ppTyVar <$> tyArgs ddef
, ("dat_" <>) $ ppVar $ tyName ddef
, "="
, interleave
"|"
(ppBody <$> dataCons ddef)
]
where
ppBody (s, lst) = text s <+> case lst of
[] -> mempty
_ -> "of" <+> parens (interleave " *" $ ppTy1 . snd <$> lst)
ppTyVar :: TyVar -> Doc
ppTyVar tyVar = case tyVar of
BoundTv var -> "'" <> ppVar var
SkolemTv _s _n -> _
UserTv var -> "'" <> ppVar var
ppTy1 :: Ty1 -> Doc
ppTy1 ty1 = case ty1 of
IntTy -> "int"
CharTy -> "char"
FloatTy -> "real"
BoolTy -> "bool"
ProdTy ty1s -> interleave " * " $ ppTy1 <$> ty1s
SymDictTy _m_var _ty1' -> _
PDictTy _ty1' _ty12 -> _
SymSetTy -> _
SymHashTy -> _
IntHashTy -> _
PackedTy s () -> " dat_" <> text s
VectorTy ty1' -> ppTy1 ty1' <+> "ArraySlice.slice"
ListTy ty1' -> ppTy1 ty1' <+> "list"
ArenaTy -> _
SymTy -> _
PtrTy -> _
CursorTy -> _
printerTy1 :: Ty1 -> Doc -> Doc
printerTy1 ty1 d = case ty1 of
IntTy -> printer "Int" d
CharTy -> printer "Char" d
FloatTy -> printer "Float" d
SymTy -> _
BoolTy -> parens $ "(fn true => print \"True\" | false => print \"False\") " <> d
ProdTy [] -> "let val () = " <> d <> " in (print \"#()\") end"
ProdTy uts ->
parens $ hsep
[ "case", d, "of"
, parens $ interleave comma $ ("x__" <>) . int . fst <$> zip [1..] uts
, "-> let"
, "val _ = print \"#(\""
, foldMap ppSub $ zip [1..] uts
, "val _ = print \")\""
, "in ()"
]
where
ppSub (i, x) = hsep
[ "val _ ="
, printerTy1 x $ "x__" <> int i
, "val _ = print \" \""
]
SymDictTy _m_var _ut -> _
PackedTy s () -> "internal_print_" <> text s <> parens d
VectorTy ut ->
parens $ hsep
[ quotePrint "#["
, toss $ hsep
[ "case length", d, "of"
, "0 -> ()"
, "1 ->", printerTy1 ut $ "ArraySlice.sub" <> parens (d <> ", 0")
, "_ ->"
, toss $ printerTy1 ut $ "ArraySlice.sub" <> parens (d <> ", 0")
, "ArraySlice.app", parens $
"fn y__ => " <> printerTy1 ut "y__"
, "xs__"
]
, "print \"]\""
]
PDictTy _ut _ut' -> _
ListTy ut ->
parens $ hsep
[ quotePrint "["
, toss $ hsep [ "case", d, "of"
, "[] -> ()"
, "| [x__] ->", printerTy1 ut "x__"
, "| [x__ :: xs__] ->"
, toss $ printerTy1 ut "x__"
, "list.app", parens $
"fn y__ => " <> quotePrint ", " <> printerTy1 ut "y__"
, "xs__"
]
, "print \"]\""
]
ArenaTy -> _
SymSetTy -> _
SymHashTy -> _
IntHashTy -> _
PtrTy -> _
CursorTy -> _
printer :: Doc -> Doc -> Doc
printer p d = parens $ "print" <> parens (p <> ".toString" <> parens d)
toss :: Doc -> Doc
toss s = "let val _ = " <> s <> " in "
justPrint :: Doc -> Doc
justPrint s = toss $ "print " <> s
quotePrint :: Doc -> Doc
quotePrint = justPrint . quotes
qsort :: Doc
qsort = parens $ text
"fn arr => fn cmp => \n\
\ let\n\
\ fun qsort(arr, lo, hi) = \n\
\ if cmp lo hi < 0 then\n\
\ let\n\
\ val pivot = ArraySlice.sub(arr, hi)\n\
\ val i = ref (lo - 1)\n\
\ val j = ref lo\n\
\ val _ = \n\
\ while cmp (!j) (hi - 1) < 1 do\n\
\ let\n\
\ val _ = \n\
\ if cmp (ArraySlice.sub(arr, !j)) pivot < 0 then\n\
\ let\n\
\ val _ = i := !i + 1\n\
\ val tmp = ArraySlice.sub(arr, !i)\n\
\ val _ = ArraySlice.update(arr, !i, ArraySlice.sub(arr, !j))\n\
\ val _ = ArraySlice.update(arr, !j, tmp)\n\
\ in\n\
\ ()\n\
\ end\n\
\ else ()\n\
\ in\n\
\ j := !j + 1\n\
\ end\n\
\ val tmp = ArraySlice.sub(arr, !i + 1)\n\
\ val _ = ArraySlice.update(arr, !i + 1, ArraySlice.sub(arr, hi))\n\
\ val _ = ArraySlice.update(arr, hi, tmp)\n\
\ val p = !i + 1\n\
\ val _ = qsort(arr, lo, p - 1)\n\
\ val _ = qsort(arr, p + 1, hi)\n\
\ in\n\
\ ()\n\
\ end\n\
\ else ()\n\
\ val _ = qsort(arr, 0, ArraySlice.length arr - 1)\n\
\ in\n\
\ arr\
\ end\n"
varsEs :: Set.Set String -> [Exp1] -> Set.Set String
varsEs = foldMap . varsE
varsE :: Set.Set String -> Exp1 -> Set.Set String
varsE vs pe0 = case pe0 of
-- VarE var -> collect var
VarE _ -> mempty
AppE var _ pes -> vpes pes <> collect var
PrimAppE _ pes -> vpes pes
LetE (_, _, _, pe') pe -> vpe pe <> vpe pe'
IfE pe pe' pe3 -> vpes [pe, pe', pe3]
MkProdE pes -> vpes pes
ProjE _ pe -> vpe pe
CaseE pe x0 -> vpe pe <> foldMap (\(_, _, pe') -> vpe pe') x0
DataConE _ _ pes -> vpes pes
TimeIt pe _ _ -> vpe pe
WithArenaE _ pe -> vpe pe
SpawnE _ _ pes -> vpes pes
SyncE -> _
MapE _ _ -> _
FoldE {} -> _
_ -> mempty
where
vpe = varsE vs
vpes = varsEs vs
collect var
| Set.member s vs = Set.singleton s
| otherwise = mempty
where s = getVar var
addFunBinding :: FunDef Var ex -> Map String (FunDef Var ex) -> Map String (FunDef Var ex)
addFunBinding funDef = Map.insert (getVar $ funName funDef) funDef
allFunEntries :: [FunDef Var ex] -> Map String (FunDef Var ex)
allFunEntries = foldr addFunBinding Map.empty
allFunNames :: [FunDef Var ex] -> Set.Set String
allFunNames = Set.fromList . fmap (getVar . funName)
getDependencies :: [FunDef Var Exp1] -> Map String [FunDef Var Exp1]
getDependencies funDefs =
foldr reduceDeps Map.empty funDefs
where
funMap = allFunEntries funDefs
funSet = allFunNames funDefs
toNode = fromMaybe _ . flip Map.lookup funMap
toDep = fmap toNode . Set.toList . varsE funSet . funBody
reduceDeps = insert . getVar . funName <*> toDep
sortDefs :: [FunDef Var Exp1] -> [[FunDef Var Exp1]]
sortDefs defs =
fmap ((\(_, n, _) -> n) . back) . flatten <$> scc gr
where
(gr, back, _) = graphFromEdges $ mkNode <$> toList depMap
mkNode (s, lst) = (s, fromMaybe _ (Map.lookup s nameMap), lst)
depMap = getDependencies defs
nameMap = fromList $ join ((,) . getVar . funName) <$> defs