Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* Copyright (C) 1999-2006 Henry Cejtin, Matthew Fluet, Suresh |
2 | * Jagannathan, and Stephen Weeks. | |
3 | * Copyright (C) 1997-2000 NEC Research Institute. | |
4 | * | |
5 | * MLton is released under a BSD-style license. | |
6 | * See the file MLton-LICENSE for details. | |
7 | *) | |
8 | ||
9 | functor DirectExp2 (S: DIRECT_EXP2_STRUCTS): DIRECT_EXP2 = | |
10 | struct | |
11 | ||
12 | open S | |
13 | ||
14 | structure DirectExp = | |
15 | struct | |
16 | ||
17 | datatype t = | |
18 | Arith of {prim: Type.t Prim.t, | |
19 | args: t vector, | |
20 | overflow: t, | |
21 | ty: Type.t} | |
22 | | Call of {func: Func.t, | |
23 | args: t vector, | |
24 | ty: Type.t} | |
25 | | Case of {cases: cases, | |
26 | default: t option, | |
27 | test: t, | |
28 | ty: Type.t} | |
29 | | ConApp of {con: Con.t, | |
30 | args: t vector, | |
31 | ty: Type.t} | |
32 | | Const of Const.t | |
33 | | Detuple of {body: Var.t vector -> t, | |
34 | length: int, | |
35 | tuple: t} | |
36 | | DetupleBind of {body: t, | |
37 | components: Var.t vector, | |
38 | tuple: Var.t, | |
39 | tupleTy: Type.t} | |
40 | | Handle of {try: t, | |
41 | catch: Var.t * Type.t, | |
42 | handler: t, | |
43 | ty: Type.t} | |
44 | | Let of {decs: {var: Var.t, exp: t} list, | |
45 | body: t} | |
46 | | Name of t * (Var.t -> t) | |
47 | | PrimApp of {prim: Type.t Prim.t, | |
48 | targs: Type.t vector, | |
49 | args: t vector, | |
50 | ty: Type.t} | |
51 | | Profile of ProfileExp.t | |
52 | | Raise of t | |
53 | | Runtime of {args: t vector, | |
54 | prim: Type.t Prim.t, | |
55 | ty: Type.t} | |
56 | | Select of {tuple: t, | |
57 | offset: int, | |
58 | ty: Type.t} | |
59 | | Seq of t * t | |
60 | | Tuple of {exps: t vector, | |
61 | ty: Type.t} | |
62 | | Var of Var.t * Type.t | |
63 | and cases = | |
64 | Con of {con: Con.t, | |
65 | args: (Var.t * Type.t) vector, | |
66 | body: t} vector | |
67 | | Word of WordSize.t * (WordX.t * t) vector | |
68 | ||
69 | val arith = Arith | |
70 | val call = Call | |
71 | val casee = Case | |
72 | val conApp = ConApp | |
73 | val const = Const | |
74 | val detuple = Detuple | |
75 | val detupleBind = DetupleBind | |
76 | val handlee = Handle | |
77 | val lett = Let | |
78 | val name = Name | |
79 | val profile = Profile | |
80 | val raisee = Raise | |
81 | val select = Select | |
82 | val seq = Seq | |
83 | val word = Const o Const.word | |
84 | ||
85 | fun tuple (r as {exps, ...}) = | |
86 | if 1 = Vector.length exps | |
87 | then Vector.first exps | |
88 | else Tuple r | |
89 | ||
90 | val var = Var | |
91 | ||
92 | fun primApp {args, prim, targs, ty} = | |
93 | let | |
94 | fun runtime () = | |
95 | Runtime {args = args, | |
96 | prim = prim, | |
97 | ty = ty} | |
98 | in | |
99 | case Prim.name prim of | |
100 | Prim.Name.MLton_halt => runtime () | |
101 | | Prim.Name.Thread_copyCurrent => runtime () | |
102 | | _ => PrimApp {args = args, | |
103 | prim = prim, | |
104 | targs = targs, | |
105 | ty = ty} | |
106 | end | |
107 | ||
108 | local | |
109 | fun make c = conApp {con = c, args = Vector.new0 (), ty = Type.bool} | |
110 | in | |
111 | val truee = make Con.truee | |
112 | val falsee = make Con.falsee | |
113 | end | |
114 | ||
115 | fun eq (e1, e2, ty) = | |
116 | primApp {prim = Prim.eq, | |
117 | targs = Vector.new1 ty, | |
118 | args = Vector.new2 (e1, e2), | |
119 | ty = Type.bool} | |
120 | ||
121 | local | |
122 | open Layout | |
123 | fun lett (decs, body) = | |
124 | align [seq [str "let ", decs], | |
125 | seq [str "in ", body], | |
126 | str "end"] | |
127 | in | |
128 | fun layout e : Layout.t = | |
129 | case e of | |
130 | Arith {prim, args, overflow, ...} => | |
131 | align [Prim.layoutApp (prim, args, layout), | |
132 | seq [str "Overflow => ", layout overflow]] | |
133 | | Call {func, args, ty} => | |
134 | seq [Func.layout func, str " ", layouts args, | |
135 | str ": ", Type.layout ty] | |
136 | | Case {cases, default, test, ...} => | |
137 | align | |
138 | [seq [str "case ", layout test, str " of"], | |
139 | indent | |
140 | (align [let | |
141 | fun doit (v, f) = | |
142 | Vector.layout | |
143 | (fn z => | |
144 | let | |
145 | val (x, e) = f z | |
146 | in | |
147 | seq [str "| ", x, str " => ", layout e] | |
148 | end) | |
149 | v | |
150 | fun simple (v, f) = | |
151 | doit (v, (fn (x, e) => (f x, e))) | |
152 | in | |
153 | case cases of | |
154 | Con v => | |
155 | doit (v, fn {con, args, body} => | |
156 | (seq [Con.layout con, | |
157 | Vector.layout (Var.layout o #1) args], | |
158 | body)) | |
159 | | Word (_, v) => simple (v, WordX.layout) | |
160 | end, | |
161 | case default of | |
162 | NONE => empty | |
163 | | SOME e => seq [str " _ => ", layout e]], | |
164 | 2)] | |
165 | | ConApp {con, args, ty} => | |
166 | seq [Con.layout con, layouts args, str ": ", Type.layout ty] | |
167 | | Const c => Const.layout c | |
168 | | Detuple {tuple, ...} => seq [str "detuple ", layout tuple] | |
169 | | DetupleBind {body, components, tuple, ...} => | |
170 | lett (seq [Vector.layout Var.layout components, | |
171 | str " = ", Var.layout tuple], | |
172 | layout body) | |
173 | | Handle {try, catch, handler, ...} => | |
174 | align [layout try, | |
175 | seq [str "handle ", Var.layout (#1 catch), | |
176 | str " => ", layout handler]] | |
177 | | Let {decs, body} => | |
178 | lett (align | |
179 | (List.map (decs, fn {var, exp} => | |
180 | seq [Var.layout var, str " = ", layout exp])), | |
181 | layout body) | |
182 | | Name _ => str "Name" | |
183 | | PrimApp {args, prim, ...} => | |
184 | Prim.layoutApp (prim, args, layout) | |
185 | | Profile e => ProfileExp.layout e | |
186 | | Raise e => seq [str "raise ", layout e] | |
187 | | Runtime {args, prim, ...} => | |
188 | Prim.layoutApp (prim, args, layout) | |
189 | | Select {tuple, offset, ...} => | |
190 | seq [str "#", str (Int.toString (1 + offset)), str " ", | |
191 | layout tuple] | |
192 | | Seq (e1, e2) => seq [layout e1, str "; ", layout e2] | |
193 | | Tuple {exps, ...} => layouts exps | |
194 | | Var (x, t) => | |
195 | seq [Var.layout x, str ": ", Type.layout t] | |
196 | and layouts es = Vector.layout layout es | |
197 | end | |
198 | ||
199 | structure Res = | |
200 | struct | |
201 | type t = {statements: Statement.t list, | |
202 | transfer: Transfer.t} | |
203 | ||
204 | fun layout {statements, transfer} = | |
205 | let | |
206 | open Layout | |
207 | in | |
208 | align [align (List.map (statements, Statement.layout)), | |
209 | Transfer.layout transfer] | |
210 | end | |
211 | ||
212 | fun prefix ({statements, transfer}: t, s: Statement.t): t = | |
213 | {statements = s :: statements, | |
214 | transfer = transfer} | |
215 | end | |
216 | ||
217 | structure Cont: | |
218 | sig | |
219 | type t | |
220 | ||
221 | val bind: Var.t * Res.t -> t | |
222 | val goto: Label.t -> t | |
223 | val layout: t -> Layout.t | |
224 | val receiveExp: (Exp.t * Type.t -> Res.t) -> t | |
225 | val receiveVar: (Var.t * Type.t -> Res.t) -> t | |
226 | val return: t | |
227 | val sendExp: t * Type.t * Exp.t -> Res.t | |
228 | val sendVar: t * Type.t * Var.t -> Res.t | |
229 | val toBlock: t * Type.t -> Block.t | |
230 | end = | |
231 | struct | |
232 | type bind = {arg: Var.t, | |
233 | statements: Statement.t list, | |
234 | transfer: Transfer.t} | |
235 | ||
236 | datatype t = | |
237 | Bind of bind | |
238 | | Goto of Label.t | |
239 | | Prefix of t * Statement.t | |
240 | | ReceiveExp of Exp.t * Type.t -> Res.t | |
241 | | ReceiveVar of Var.t * Type.t -> Res.t | |
242 | | Return | |
243 | ||
244 | fun layout (k: t): Layout.t = | |
245 | let | |
246 | open Layout | |
247 | in | |
248 | case k of | |
249 | Bind {arg, statements, transfer} => | |
250 | seq [str "Bind ", | |
251 | record [("arg", Var.layout arg), | |
252 | ("statements", | |
253 | List.layout Statement.layout statements), | |
254 | ("transfer", Transfer.layout transfer)]] | |
255 | | Goto l => seq [str "Goto ", Label.layout l] | |
256 | | Prefix (k, s) => seq [str "Prefix ", | |
257 | tuple [layout k, Statement.layout s]] | |
258 | | ReceiveExp _ => str "ReceiveExp" | |
259 | | ReceiveVar _ => str "ReceiveVar" | |
260 | | Return => str "Return" | |
261 | end | |
262 | ||
263 | fun bind (arg, {statements, transfer}) = | |
264 | Bind {arg = arg, | |
265 | statements = statements, | |
266 | transfer = transfer} | |
267 | ||
268 | val goto = Goto | |
269 | val receiveExp = ReceiveExp | |
270 | val receiveVar = ReceiveVar | |
271 | val return = Return | |
272 | ||
273 | fun toBind (k: t, ty: Type.t): bind = | |
274 | case k of | |
275 | Bind b => b | |
276 | | _ => | |
277 | let | |
278 | val arg = Var.newNoname () | |
279 | val {statements, transfer} = sendVar (k, ty, arg) | |
280 | in | |
281 | {arg = arg, | |
282 | statements = statements, | |
283 | transfer = transfer} | |
284 | end | |
285 | and sendVar (k: t, ty: Type.t, x: Var.t): Res.t = | |
286 | case k of | |
287 | Bind b => sendBindExp (b, ty, Exp.Var x) | |
288 | | Goto dst => {statements = [], | |
289 | transfer = Transfer.Goto {dst = dst, | |
290 | args = Vector.new1 x}} | |
291 | | ReceiveExp f => f (Exp.Var x, ty) | |
292 | | ReceiveVar f => f (x, ty) | |
293 | | Prefix (k, s) => Res.prefix (sendVar (k, ty, x), s) | |
294 | | Return => {statements = [], | |
295 | transfer = Transfer.Return (Vector.new1 x)} | |
296 | and sendBindExp ({arg, statements, transfer}, ty, e: Exp.t) = | |
297 | {statements = Statement.T {var = SOME arg, | |
298 | ty = ty, | |
299 | exp = e} :: statements, | |
300 | transfer = transfer} | |
301 | ||
302 | val sendVar = | |
303 | Trace.trace3 ("DirectExp2.Cont.sendVar", layout, Type.layout, Var.layout, | |
304 | Res.layout) | |
305 | sendVar | |
306 | ||
307 | val sendExp: t * Type.t * Exp.t -> Res.t = | |
308 | fn (k, ty, e) => | |
309 | case k of | |
310 | ReceiveExp f => f (e, ty) | |
311 | | _ => sendBindExp (toBind (k, ty), ty, e) | |
312 | ||
313 | val sendExp = | |
314 | Trace.trace3 ("DirectExp2.Cont.sendExp", layout, Type.layout, Exp.layout, | |
315 | Res.layout) | |
316 | sendExp | |
317 | ||
318 | fun toBlock (k: t, ty: Type.t): Block.t = | |
319 | let | |
320 | val {arg, statements, transfer} = toBind (k, ty) | |
321 | val label = Label.newNoname () | |
322 | in | |
323 | Block.T {label = label, | |
324 | args = Vector.new1 (arg, ty), | |
325 | statements = Vector.fromList statements, | |
326 | transfer = transfer} | |
327 | end | |
328 | ||
329 | val toBlock = | |
330 | Trace.trace2 ("DirectExp2.Cont.toBlock", layout, Type.layout, Block.layout) | |
331 | toBlock | |
332 | end | |
333 | ||
334 | fun selects (tuple: Var.t, ty: Type.t, components: Var.t vector) | |
335 | : Statement.t list = | |
336 | let | |
337 | val ts = Type.deTuple ty | |
338 | in | |
339 | Vector.foldi | |
340 | (ts, [], fn (i, t, ss) => | |
341 | Statement.T {var = SOME (Vector.sub (components, i)), | |
342 | ty = t, | |
343 | exp = Exp.Select {tuple = tuple, | |
344 | offset = i}} | |
345 | :: ss) | |
346 | end | |
347 | ||
348 | fun linearize' (e: t, h: Handler.t, k: Cont.t): Label.t * Block.t list = | |
349 | let | |
350 | val traceLinearizeLoop = | |
351 | Trace.trace3 ("DirectExp.linearize'.loop", layout, Handler.layout, Cont.layout, | |
352 | Res.layout) | |
353 | val blocks: Block.t list ref = ref [] | |
354 | fun newBlock (args: (Var.t * Type.t) vector, | |
355 | {statements: Statement.t list, | |
356 | transfer: Transfer.t}): Label.t = | |
357 | let | |
358 | val label = Label.newNoname () | |
359 | val _ = List.push (blocks, | |
360 | Block.T {label = label, | |
361 | args = args, | |
362 | statements = Vector.fromList statements, | |
363 | transfer = transfer}) | |
364 | in | |
365 | label | |
366 | end | |
367 | fun reify (k: Cont.t, ty: Type.t): Label.t = | |
368 | let | |
369 | val b = Cont.toBlock (k, ty) | |
370 | val _ = List.push (blocks, b) | |
371 | in | |
372 | Block.label b | |
373 | end | |
374 | fun newLabel (args: (Var.t * Type.t) vector, | |
375 | e: t, | |
376 | h: Handler.t, | |
377 | k: Cont.t): Label.t = | |
378 | newBlock (args, loop (e, h, k)) | |
379 | and newLabel0 (e, h, k) = newLabel (Vector.new0 (), e, h, k) | |
380 | and loopf (e: t, h: Handler.t, f: Var.t * Type.t -> Res.t) = | |
381 | loop (e, h, Cont.receiveVar f) | |
382 | and loop arg : Res.t = | |
383 | traceLinearizeLoop | |
384 | (fn (e: t, h: Handler.t, k: Cont.t) => | |
385 | case e of | |
386 | Arith {prim, args, overflow, ty} => | |
387 | loops | |
388 | (args, h, fn xs => | |
389 | let | |
390 | val l = reify (k, ty) | |
391 | val k = Cont.goto l | |
392 | in | |
393 | {statements = [], | |
394 | transfer = | |
395 | Transfer.Arith {prim = prim, | |
396 | args = xs, | |
397 | overflow = newLabel0 (overflow, h, k), | |
398 | success = l, | |
399 | ty = ty}} | |
400 | end) | |
401 | | Call {func, args, ty} => | |
402 | loops | |
403 | (args, h, fn xs => | |
404 | {statements = [], | |
405 | transfer = (Transfer.Call | |
406 | {func = func, | |
407 | args = xs, | |
408 | return = Return.NonTail {cont = reify (k, ty), | |
409 | handler = h}})}) | |
410 | | Case {cases, default, test, ty} => | |
411 | let | |
412 | val k = Cont.goto (reify (k, ty)) | |
413 | in | |
414 | loopf (test, h, fn (x, _) => | |
415 | {statements = [], | |
416 | transfer = | |
417 | Transfer.Case | |
418 | {test = x, | |
419 | default = Option.map (default, fn e => | |
420 | newLabel0 (e, h, k)), | |
421 | cases = | |
422 | let | |
423 | fun doit v = | |
424 | Vector.map (v, fn (c, e) => | |
425 | (c, newLabel0 (e, h, k))) | |
426 | in | |
427 | case cases of | |
428 | Con v => | |
429 | Cases.Con | |
430 | (Vector.map | |
431 | (v, fn {con, args, body} => | |
432 | (con, | |
433 | newLabel (args, body, h, k)))) | |
434 | | Word (s, v) => Cases.Word (s, doit v) | |
435 | end}}) | |
436 | end | |
437 | | ConApp {con, args, ty} => | |
438 | loops (args, h, fn xs => | |
439 | Cont.sendExp (k, ty, Exp.ConApp {con = con, args = xs})) | |
440 | | Const c => Cont.sendExp (k, Type.ofConst c, Exp.Const c) | |
441 | | Detuple {tuple, length, body} => | |
442 | loop (tuple, h, | |
443 | Cont.receiveExp | |
444 | (fn (e, ty) => | |
445 | let | |
446 | fun doit (tuple: Var.t): Res.t = | |
447 | let | |
448 | val (ss, xs) = | |
449 | case length of | |
450 | 0 => ([], Vector.new0 ()) | |
451 | | 1 => ([], Vector.new1 tuple) | |
452 | | _ => | |
453 | let | |
454 | val xs = | |
455 | Vector.tabulate | |
456 | (length, fn _ => Var.newNoname ()) | |
457 | in (selects (tuple, ty, xs), xs) | |
458 | end | |
459 | val {statements, transfer} = loop (body xs, h, k) | |
460 | in | |
461 | {statements = List.appendRev (ss, statements), | |
462 | transfer = transfer} | |
463 | end | |
464 | in | |
465 | case e of | |
466 | Exp.Tuple xs => loop (body xs, h, k) | |
467 | | Exp.Var x => doit x | |
468 | | _ => | |
469 | let | |
470 | val tuple = Var.newNoname () | |
471 | in | |
472 | Res.prefix (doit tuple, | |
473 | Statement.T {var = SOME tuple, | |
474 | ty = ty, | |
475 | exp = e}) | |
476 | end | |
477 | end)) | |
478 | | DetupleBind {body, components, tuple, tupleTy} => | |
479 | let | |
480 | val {statements, transfer} = loop (body, h, k) | |
481 | val ss = | |
482 | case Vector.length components of | |
483 | 0 => [] | |
484 | | 1 => [Statement.T | |
485 | {var = SOME (Vector.first components), | |
486 | ty = tupleTy, | |
487 | exp = Exp.Var tuple}] | |
488 | | _ => selects (tuple, tupleTy, components) | |
489 | in | |
490 | {statements = List.appendRev (ss, statements), | |
491 | transfer = transfer} | |
492 | end | |
493 | | Handle {try, catch, handler, ty} => | |
494 | let | |
495 | val k = Cont.goto (reify (k, ty)) | |
496 | val hl = Label.newNoname () | |
497 | val {statements, transfer} = loop (handler, h, k) | |
498 | val _ = | |
499 | List.push (blocks, | |
500 | Block.T {label = hl, | |
501 | args = Vector.new1 catch, | |
502 | statements = Vector.fromList statements, | |
503 | transfer = transfer}) | |
504 | in | |
505 | loop (try, Handler.Handle hl, k) | |
506 | end | |
507 | | Let {decs, body} => | |
508 | let | |
509 | fun each decs = | |
510 | case decs of | |
511 | [] => loop (body, h, k) | |
512 | | {var, exp} :: decs => | |
513 | loop (exp, h, Cont.bind (var, each decs)) | |
514 | in | |
515 | each decs | |
516 | end | |
517 | | Name (e, f) => loopf (e, h, fn (x, _) => loop (f x, h, k)) | |
518 | | PrimApp {prim, targs, args, ty} => | |
519 | loops | |
520 | (args, h, fn xs => | |
521 | Cont.sendExp (k, ty, Exp.PrimApp {prim = prim, | |
522 | targs = targs, | |
523 | args = xs})) | |
524 | | Profile e => Cont.sendExp (k, Type.unit, Exp.Profile e) | |
525 | | Raise e => | |
526 | loopf (e, h, fn (x, _) => | |
527 | {statements = [], | |
528 | transfer = | |
529 | (case h of | |
530 | Handler.Caller => Transfer.Raise (Vector.new1 x) | |
531 | | Handler.Dead => Error.bug "DirectExp2.linearize'.loop: Raise:to dead handler" | |
532 | | Handler.Handle l => | |
533 | Transfer.Goto {args = Vector.new1 x, | |
534 | dst = l})}) | |
535 | | Runtime {args, prim, ty} => | |
536 | loops | |
537 | (args, h, fn xs => | |
538 | let | |
539 | val l = reify (k, ty) | |
540 | val k = Cont.goto l | |
541 | val (args, exps) = | |
542 | case Type.deTupleOpt ty of | |
543 | NONE => | |
544 | let | |
545 | val res = Var.newNoname () | |
546 | in | |
547 | (Vector.new1 (res, ty), | |
548 | Vector.new1 (Var (res, ty))) | |
549 | end | |
550 | | SOME ts => | |
551 | if Vector.isEmpty ts | |
552 | then (Vector.new0 (), Vector.new0 ()) | |
553 | else | |
554 | Error.bug | |
555 | (concat ["DirectExp2.linearlize'.loop: Runtime:with multiple return values: ", | |
556 | Prim.toString prim]) | |
557 | in | |
558 | {statements = [], | |
559 | transfer = | |
560 | Transfer.Runtime | |
561 | {prim = prim, | |
562 | args = xs, | |
563 | return = newLabel (args, | |
564 | tuple {exps = exps, | |
565 | ty = ty}, | |
566 | h, k)}} | |
567 | end) | |
568 | | Select {tuple, offset, ty} => | |
569 | loopf (tuple, h, fn (tuple, _) => | |
570 | Cont.sendExp (k, ty, Exp.Select {tuple = tuple, | |
571 | offset = offset})) | |
572 | | Seq (e1, e2) => loopf (e1, h, fn _ => loop (e2, h, k)) | |
573 | | Tuple {exps, ty} => | |
574 | loops (exps, h, fn xs => Cont.sendExp (k, ty, Exp.Tuple xs)) | |
575 | | Var (x, ty) => Cont.sendVar (k, ty, x)) arg | |
576 | and loops (es: t vector, h: Handler.t, k: Var.t vector -> Res.t): Res.t = | |
577 | let | |
578 | val n = Vector.length es | |
579 | fun each (i, ac) = | |
580 | if i = n | |
581 | then k (Vector.fromListRev ac) | |
582 | else loopf (Vector.sub (es, i), h, fn (x, _) => | |
583 | each (i + 1, x :: ac)) | |
584 | in | |
585 | each (0, []) | |
586 | end | |
587 | val l = newLabel0 (e, h, k) | |
588 | in | |
589 | (l, !blocks) | |
590 | end | |
591 | ||
592 | fun linearize (e: t, h) = linearize' (e, h, Cont.return) | |
593 | ||
594 | val linearize = | |
595 | Trace.trace2 ("DirectExp2.linearize", layout, Handler.layout, | |
596 | Layout.tuple2 (Label.layout, | |
597 | List.layout (Label.layout o Block.label))) | |
598 | linearize | |
599 | ||
600 | fun linearizeGoto (e: t, h, l) = linearize' (e, h, Cont.goto l) | |
601 | ||
602 | end | |
603 | end |