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
|
implementation module utilities
// compile using the "reuse unique nodes option"
import StdEnv, general
/*
Utility routines.
*/
StringToCharList` :: !String !Int !Int -> [Char]
StringToCharList` string 0 index
= []
StringToCharList` string length index
= [string.[index] : StringToCharList` string (dec length) (inc index)]
stringToCharList :: !String -> [Char]
stringToCharList string = StringToCharList` string (size string) 0
charListToString :: ![Char] -> String
charListToString [hd:tl] = toString hd +++ charListToString tl
charListToString [] = ""
revCharListToString :: !Int ![Char] -> String
revCharListToString max_index l
# string = createArray (max_index + 1) '\0'
= fill_string max_index l string
where
fill_string :: !Int ![Char] !*String -> *String
fill_string n [ char : rest] string
= fill_string (n - 1) rest { string & [n] = char }
fill_string (-1) [] string
= string
/*
revCharListToString [hd:tl] = revCharListToString tl +++ toString hd
revCharListToString [] = ""
*/
skipUnderscores :: !Int !Int !String -> Char
skipUnderscores i size s
| i < size
#! c = s.[i]
| c == '_'
= skipUnderscores (i+1) size s
= c
// otherwise: i >= size
= '_'
isUpperCaseName :: ! String -> Bool
isUpperCaseName id
#! c = skipUnderscores 0 (size id) id
= 'A' <= c && c <= 'Z'
isLowerCaseName :: ! String -> Bool
isLowerCaseName id
#! c = skipUnderscores 0 (size id) id
= 'a' <= c && c <= 'z'
isFunnyIdName :: ! String -> Bool
isFunnyIdName id
= isSpecialChar id.[0]
isSpecialChar :: !Char -> Bool
isSpecialChar '~' = True
isSpecialChar '@' = True
isSpecialChar '#' = True
isSpecialChar '$' = True
isSpecialChar '%' = True
isSpecialChar '^' = True
isSpecialChar '?' = True
isSpecialChar '!' = True
isSpecialChar '+' = True
isSpecialChar '-' = True
isSpecialChar '*' = True
isSpecialChar '<' = True
isSpecialChar '>' = True
isSpecialChar '\\' = True
isSpecialChar '/' = True
isSpecialChar '|' = True
isSpecialChar '&' = True
isSpecialChar '=' = True
isSpecialChar ':' = True
isSpecialChar '.' = True
isSpecialChar c = False
isNotEmpty :: ![a] -> Bool
isNotEmpty [] = False
isNotEmpty _ = True
strictMap :: !(.a -> .b) ![.a] -> [.b]
strictMap f [x : xs]
#! head = f x
tail = strictMap f xs
= [head : tail]
strictMap f xs
= []
strictMapAppend :: !(.a -> .b) ![.a] !u:[.b] -> v:[.b], [u <= v]
strictMapAppend f [x : xs] tail
#! x = f x
xs = strictMapAppend f xs tail
= [x : xs]
strictMapAppend f [] tail
= tail
mapAppend :: !(.a -> .b) ![.a] !u:[.b] -> u:[.b]
mapAppend f [x : xs] tail
# x = f x
xs = mapAppend f xs tail
= [x : xs]
mapAppend f [] tail
= tail
mapAppendSt :: !(.a -> .(.b -> (.c,.b))) ![.a] !u:[.c] !.b -> (!u:[.c],!.b)
mapAppendSt f [x : xs] tail s
# (x, s) = f x s
(xs, s) = mapAppendSt f xs tail s
= ([x : xs], s)
mapAppendSt f [] tail s
= (tail, s)
/*
mapSt :: !(.a -> (.st -> (.c,.st))) ![.a] !.st -> (![.c],!.st)
mapSt f [x : xs] s
# (x, s) = f x s
(xs, s) = mapSt f xs s
= ([x : xs], s)
mapSt f [] s
= ([], s)
*/
//mapSt :: !(.a -> (.st -> (.c,.st))) ![.a] !.st -> (![.c],!.st)
mapSt f l s :== map_st l s
where
map_st [x : xs] s
# (x, s) = f x s
(xs, s) = map_st xs s
#! s = s
= ([x : xs], s)
map_st [] s
#! s = s
= ([], s)
mapSt2 f l s1 s2 :== map_st2 l s1 s2
where
map_st2 [x : xs] s1 s2
# (x, s1,s2) = f x s1 s2
(xs, s1,s2) = map_st2 xs s1 s2
#! s1 = s1
#! s2 = s2
= ([x : xs], s1,s2)
map_st2 [] s1 s2
= ([], s1,s2)
mapY2St f l s :== map_y2_st l s
where
map_y2_st [x : xs] s
# (x, y, s) = f x s
(xs, ys, s) = map_y2_st xs s
#! s = s
= ([x : xs], [y : ys], s)
map_y2_st [] s
#! s = s
= ([], [], s)
map2St f l1 l2 st :== map2_st l1 l2 st
where
map2_st [h1:t1] [h2:t2] st
# (h, st) = f h1 h2 st
(t, st) = map2_st t1 t2 st
#! st = st
= ([h:t], st)
map2_st _ _ st
#! st = st
= ([], st)
app2St :: !(!.(.a -> .(.st -> (.c,.st))),!.(.e -> .(.st -> (.f,.st)))) !(.a,.e) !.st -> (!(.c,.f),!.st)
app2St (f,g) (x,y) s
# (x, s) = f x s
(y, s) = g y s
= ((x,y), s)
// foldl2 :: !(.c -> .(.a -> .(.b -> .c))) !.c ![.a] ![.b] -> .c
foldl2 op r l1 l2
:== foldl2 r l1 l2
where
foldl2 r [x : xs] [y : ys]
= foldl2 (op r x y) xs ys
foldl2 r [] []
= r
//foldr2 :: !(.a -> .(.b -> .(.c -> .c))) !.c ![.a] ![.b] -> .c
foldr2 op r l1 l2
:== foldr2 r l1 l2
where
foldr2 r [x : xs] [y : ys]
= op x y (foldr2 r xs ys)
foldr2 r [] []
= r
fold2St op l1 l2 st
:== fold_st2 l1 l2 st
where
fold_st2 [x : xs] [y : ys] st
= op x y (fold_st2 xs ys st)
fold_st2 [] [] st
= st
fold_st2 [] ys st
= abort ("fold_st2: second argument list contains more elements")
fold_st2 xs [] st
= abort ("fold_st2: first argument list contains more elements")
unsafeFold2St op l1 l2 st
:== ufold_st2 l1 l2 st
where
ufold_st2 [x : xs] [y : ys] st
= ufold_st2 xs ys (op x y st)
ufold_st2 _ _ st
= st
unsafeFold3St op l1 l2 l3 st
:== ufold_st3 l1 l2 l3 st
where
ufold_st3 [x : xs] [y : ys] [z : zs] st
= ufold_st3 xs ys zs (op x y z st)
ufold_st3 _ _ _ st
= st
// foldSt :: !(.a -> .(.st -> .st)) ![.a] !.st -> .st
foldSt op r l :== fold_st r l
where
fold_st [] st = st
fold_st [a:x] st = fold_st x (op a st)
// iFoldSt :: (Int -> .(.b -> .b)) !Int !Int .b -> .b
iFoldSt op fr to st :== i_fold_st fr to st
where
i_fold_st fr to st
| fr >= to
= st
= i_fold_st (inc fr) to (op fr st)
iterateSt op st :== iterate_st op st
where
iterate_st op st
# (continue, st) = op st
| continue
= iterate_st op st
= st
mapFilterYesSt f l st
:== map_filter_yes_st l st
where
map_filter_yes_st [] st
#! st = st
= ([], st)
map_filter_yes_st [h:t] st
#! (opt_f_h , st) = f h st
(t2, st) = map_filter_yes_st t st
(f_h_t2, _) = optCons opt_f_h t2
st = st
= (f_h_t2, st)
iMapFilterYesSt f fr to st
:== i_map_filter_yes_st fr to st
where
i_map_filter_yes_st fr to st
#! st = st
| fr >= to
= ([], st)
#! (opt_f_fr, st) = f fr st
(t, st) = i_map_filter_yes_st (inc fr) to st
(f_fr_t2, _) = optCons opt_f_fr t
st = st
= (f_fr_t2, st)
foldlArrayStWithIndex f a st :== fold_a_st_i 0 a st
where
fold_a_st_i i a st
| i==size a
= st
# (ai, a) = a![i]
= fold_a_st_i (i+1) a (f i ai st)
foldlArraySt f a st :== fold_a_st 0 a st
where
fold_a_st i a st
| i==size a
= st
# (ai, a) = a![i]
= fold_a_st (i+1) a (f ai st)
foldrArraySt f a st
:== foldr_a_st (size a-1) a st
where
foldr_a_st i a st
| i==(-1)
= st
# (ai, a) = a![i]
= foldr_a_st (i-1) a (f ai st)
firstIndex p l :== first_index l 0
where
first_index [] i
= (i-i)-1
first_index [h:t] i
| p h
= i
= first_index t (i+1)
optCons :: !(Optional .a) !u:[.a] -> (!v:[.a], !Int) ,[u <= v]
optCons No l
= (l, 0)
optCons (Yes x) l
= ([x:l], 0)
eqMerge :: ![a] ![a] -> [a] | Eq a
eqMerge [a : x] y
| isMember a y
= eqMerge x y
= [a : eqMerge x y]
eqMerge x y
= y
revAppend :: ![a] ![a] -> [a] // Reverse the list using the second argument as accumulator.
revAppend [] acc = acc
revAppend [x : xs] acc = revAppend xs [x : acc]
revMap :: !(.a -> .b) ![.a] !u:[.b] -> u:[.b]
revMap f [] acc = acc
revMap f [x : xs] acc = revMap f xs [f x : acc]
/*
zip2Append :: [.a] [.b] u:[w:(.a,.b)] -> v:[x:(.a,.b)], [w <= x, u <= v]
zip2Append [] [] tail
= tail
zip2Append [x : xs] [y : ys] tail
= [(x,y) : zip2Append xs ys tail]
*/
:: Bag x = Empty | Single !x | Pair !(Bag x) !(Bag x)
uniqueBagToList :: !*(Bag x) -> [x] // exploits reuse of unique nodes (if compiled with that option)
uniqueBagToList bag
= accumulate_elements bag []
where
accumulate_elements :: !*(Bag x) [x] -> [x]
accumulate_elements Empty accu
= accu
accumulate_elements (Single element) accu
= [element : accu]
accumulate_elements (Pair bag1 bag2) accu
= accumulate_elements bag1 (accumulate_elements bag2 accu)
bagToList :: !(Bag x) -> [x]
bagToList bag
= accumulate_elements bag []
where
accumulate_elements :: !(Bag x) [x] -> [x]
accumulate_elements Empty accu
= accu
accumulate_elements (Single element) accu
= [element : accu]
accumulate_elements (Pair bag1 bag2) accu
= accumulate_elements bag1 (accumulate_elements bag2 accu)
isEmptyBag :: !(Bag x) -> Bool
isEmptyBag Empty = True
isEmptyBag _ = False
:: DAG =
{ dag_nr_of_nodes :: !Int
, dag_get_children :: !Int -> [Int]
}
:: PartitioningState =
{ ps_marks :: !.{# Int}
, ps_next_num :: !Int
, ps_groups :: ![[Int]]
, ps_deps :: ![Int]
}
NotChecked :== -1
partitionateDAG :: !DAG ![Int] -> [[Int]]
partitionateDAG pi=:{dag_nr_of_nodes} roots
# partitioning_info
= { ps_marks = createArray dag_nr_of_nodes NotChecked, ps_deps = [],
ps_next_num = 0, ps_groups = [] }
{ps_groups}
= foldSt (partitionate_node pi) roots partitioning_info
= ps_groups
where
partitionate_node :: !DAG !Int !*PartitioningState -> *PartitioningState
partitionate_node pi node_index ps=:{ps_marks}
| ps_marks.[node_index] == NotChecked
= snd (partitionate_unvisited_node node_index pi ps)
= ps
partitionate_unvisited_node :: !Int !DAG !*PartitioningState
-> (!Int, !*PartitioningState)
partitionate_unvisited_node node_index pi ps=:{ps_next_num}
# children
= pi.dag_get_children node_index
(min_dep, ps)
= visit_children children pi.dag_nr_of_nodes pi (push_on_dep_stack node_index ps)
= try_to_close_group node_index ps_next_num min_dep pi ps
push_on_dep_stack :: !Int !*PartitioningState -> *PartitioningState
push_on_dep_stack node_index ps=:{ps_deps,ps_marks,ps_next_num}
= { ps & ps_deps = [node_index : ps_deps], ps_marks = { ps_marks & [node_index] = ps_next_num},
ps_next_num = inc ps_next_num}
visit_children :: ![Int] !Int !DAG !*PartitioningState -> (!Int, !*PartitioningState)
visit_children [child:children] min_dep pi ps=:{ps_marks}
#! mark = ps_marks.[child]
| mark == NotChecked
# (mark, ps) = partitionate_unvisited_node child pi ps
= visit_children children (min min_dep mark) pi ps
= visit_children children (min min_dep mark) pi ps
visit_children [] min_dep nr_of_nodes ps
= (min_dep, ps)
try_to_close_group :: !Int !Int !Int !DAG !*PartitioningState -> (!Int, !*PartitioningState)
try_to_close_group node_index next_num min_dep pi ps=:{ps_marks, ps_deps, ps_groups}
| next_num <= min_dep
# (ps_deps, ps_marks, group)
= close_group node_index ps_deps ps_marks [] pi
ps = { ps & ps_deps = ps_deps, ps_marks = ps_marks, ps_groups = [group : ps_groups] }
= (pi.dag_nr_of_nodes, ps)
= (min_dep, ps)
close_group :: !Int ![Int] !*{# Int} ![Int] !DAG -> (![Int], !*{# Int}, ![Int])
close_group node_index [d:ds] marks group pi
# marks = { marks & [d] = pi.dag_nr_of_nodes }
| d == node_index
= (ds, marks, [d : group])
= close_group node_index ds marks [d : group] pi
|