Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* Copyright (C) 2017 Matthew Fluet. |
2 | * Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh | |
3 | * Jagannathan, and Stephen Weeks. | |
4 | * Copyright (C) 1997-2000 NEC Research Institute. | |
5 | * | |
6 | * MLton is released under a BSD-style license. | |
7 | * See the file MLton-LICENSE for details. | |
8 | *) | |
9 | ||
10 | functor XmlTree (S: XML_TREE_STRUCTS): XML_TREE = | |
11 | struct | |
12 | ||
13 | open S | |
14 | ||
15 | structure Type = | |
16 | struct | |
17 | structure T = HashType (S) | |
18 | open T | |
19 | ||
20 | datatype dest = | |
21 | Var of Tyvar.t | |
22 | | Con of Tycon.t * t vector | |
23 | ||
24 | fun dest t = | |
25 | case Dest.dest t of | |
26 | Dest.Var a => Var a | |
27 | | Dest.Con x => Con x | |
28 | end | |
29 | ||
30 | fun maybeConstrain (x, t) = | |
31 | let | |
32 | open Layout | |
33 | in | |
34 | if !Control.showTypes | |
35 | then seq [x, str " : ", Type.layout t] | |
36 | else x | |
37 | end | |
38 | ||
39 | local | |
40 | open Layout | |
41 | in | |
42 | fun layoutTargs (ts: Type.t vector) = | |
43 | if !Control.showTypes | |
44 | andalso 0 < Vector.length ts | |
45 | then list (Vector.toListMap (ts, Type.layout)) | |
46 | else empty | |
47 | end | |
48 | ||
49 | structure Pat = | |
50 | struct | |
51 | datatype t = T of {arg: (Var.t * Type.t) option, | |
52 | con: Con.t, | |
53 | targs: Type.t vector} | |
54 | ||
55 | local | |
56 | open Layout | |
57 | in | |
58 | fun layout (T {arg, con, targs}) = | |
59 | seq [Con.layout con, | |
60 | layoutTargs targs, | |
61 | case arg of | |
62 | NONE => empty | |
63 | | SOME (x, t) => | |
64 | maybeConstrain (seq [str " ", Var.layout x], t)] | |
65 | end | |
66 | ||
67 | fun con (T {con, ...}) = con | |
68 | ||
69 | local | |
70 | fun make c = T {con = c, targs = Vector.new0 (), arg = NONE} | |
71 | in | |
72 | val falsee = make Con.falsee | |
73 | val truee = make Con.truee | |
74 | end | |
75 | end | |
76 | ||
77 | structure Cases = | |
78 | struct | |
79 | datatype 'a t = | |
80 | Con of (Pat.t * 'a) vector | |
81 | | Word of WordSize.t * (WordX.t * 'a) vector | |
82 | ||
83 | fun layout (cs, layout) = | |
84 | let | |
85 | open Layout | |
86 | fun doit (v, f) = | |
87 | align (Vector.toListMap (v, fn (x, e) => | |
88 | align [seq [f x, str " => "], | |
89 | indent (layout e, 3)])) | |
90 | in | |
91 | case cs of | |
92 | Con v => doit (v, Pat.layout) | |
93 | | Word (_, v) => doit (v, WordX.layout) | |
94 | end | |
95 | ||
96 | fun fold (c: 'a t, b: 'b, f: 'a * 'b -> 'b): 'b = | |
97 | let | |
98 | fun doit l = Vector.fold (l, b, fn ((_, a), b) => f (a, b)) | |
99 | in | |
100 | case c of | |
101 | Con l => doit l | |
102 | | Word (_, l) => doit l | |
103 | end | |
104 | ||
105 | fun map (c: 'a t, f: 'a -> 'b): 'b t = | |
106 | let | |
107 | fun doit l = Vector.map (l, fn (i, x) => (i, f x)) | |
108 | in | |
109 | case c of | |
110 | Con l => Con (doit l) | |
111 | | Word (s, l) => Word (s, doit l) | |
112 | end | |
113 | ||
114 | fun foreach (c, f) = fold (c, (), fn (x, ()) => f x) | |
115 | ||
116 | fun foreach' (c: 'a t, f: 'a -> unit, fc: Pat.t -> unit): unit = | |
117 | let | |
118 | fun doit l = Vector.foreach (l, fn (_, a) => f a) | |
119 | in | |
120 | case c of | |
121 | Con l => Vector.foreach (l, fn (c, a) => (fc c; f a)) | |
122 | | Word (_, l) => doit l | |
123 | end | |
124 | end | |
125 | ||
126 | structure VarExp = | |
127 | struct | |
128 | datatype t = T of {targs: Type.t vector, | |
129 | var: Var.t} | |
130 | ||
131 | fun equals (T {targs = targs1, var = var1}, | |
132 | T {targs = targs2, var = var2}) = | |
133 | Var.equals (var1, var2) | |
134 | andalso Vector.equals (targs1, targs2, Type.equals) | |
135 | ||
136 | fun mono var = T {var = var, targs = Vector.new0 ()} | |
137 | ||
138 | local | |
139 | fun make f (T r) = f r | |
140 | in | |
141 | val var = make #var | |
142 | end | |
143 | ||
144 | fun layout (T {var, targs, ...}) = | |
145 | if !Control.showTypes | |
146 | then let open Layout | |
147 | in | |
148 | if Vector.isEmpty targs | |
149 | then Var.layout var | |
150 | else seq [Var.layout var, str " ", | |
151 | Vector.layout Type.layout targs] | |
152 | end | |
153 | else Var.layout var | |
154 | end | |
155 | ||
156 | (*---------------------------------------------------*) | |
157 | (* Expressions and Declarations *) | |
158 | (*---------------------------------------------------*) | |
159 | ||
160 | datatype exp = | |
161 | Exp of {decs: dec list, | |
162 | result: VarExp.t} | |
163 | and primExp = | |
164 | App of {func: VarExp.t, | |
165 | arg: VarExp.t} | |
166 | | Case of {test: VarExp.t, | |
167 | cases: exp Cases.t, | |
168 | default: (exp * Region.t) option} | |
169 | | ConApp of {con: Con.t, | |
170 | targs: Type.t vector, | |
171 | arg: VarExp.t option} | |
172 | | Const of Const.t | |
173 | | Handle of {try: exp, | |
174 | catch: Var.t * Type.t, | |
175 | handler: exp} | |
176 | | Lambda of lambda | |
177 | | PrimApp of {args: VarExp.t vector, | |
178 | prim: Type.t Prim.t, | |
179 | targs: Type.t vector} | |
180 | | Profile of ProfileExp.t | |
181 | | Raise of {exn: VarExp.t, extend: bool} | |
182 | | Select of {tuple: VarExp.t, | |
183 | offset: int} | |
184 | | Tuple of VarExp.t vector | |
185 | | Var of VarExp.t | |
186 | and dec = | |
187 | Exception of {arg: Type.t option, | |
188 | con: Con.t} | |
189 | | Fun of {decs: {lambda: lambda, | |
190 | ty: Type.t, | |
191 | var: Var.t} vector, | |
192 | tyvars: Tyvar.t vector} | |
193 | | MonoVal of {exp: primExp, | |
194 | ty: Type.t, | |
195 | var: Var.t} | |
196 | | PolyVal of {exp: exp, | |
197 | ty: Type.t, | |
198 | tyvars: Tyvar.t vector, | |
199 | var: Var.t} | |
200 | and lambda = Lam of {arg: Var.t, | |
201 | argType: Type.t, | |
202 | body: exp, | |
203 | mayInline: bool, | |
204 | plist: PropertyList.t} | |
205 | ||
206 | local | |
207 | open Layout | |
208 | in | |
209 | fun layoutConArg {arg, con} = | |
210 | seq [Con.layout con, | |
211 | case arg of | |
212 | NONE => empty | |
213 | | SOME t => seq [str " of ", Type.layout t]] | |
214 | fun layoutTyvars ts = | |
215 | case Vector.length ts of | |
216 | 0 => empty | |
217 | | _ => seq [tuple (Vector.toListMap (ts, Tyvar.layout)), str " "] | |
218 | fun layoutDec d = | |
219 | case d of | |
220 | Exception ca => | |
221 | seq [str "exception ", layoutConArg ca] | |
222 | | Fun {decs, tyvars} => | |
223 | align [seq [str "val rec ", layoutTyvars tyvars], | |
224 | indent (align (Vector.toListMap | |
225 | (decs, fn {lambda, ty, var} => | |
226 | align [seq [maybeConstrain (Var.layout var, ty), | |
227 | str " = "], | |
228 | indent (layoutLambda lambda, 3)])), | |
229 | 3)] | |
230 | | MonoVal {exp, ty, var} => | |
231 | align [seq [str "val ", | |
232 | maybeConstrain (Var.layout var, ty), str " = "], | |
233 | indent (layoutPrimExp exp, 3)] | |
234 | | PolyVal {exp, ty, tyvars, var} => | |
235 | align [seq [str "val ", | |
236 | if !Control.showTypes | |
237 | then layoutTyvars tyvars | |
238 | else empty, | |
239 | maybeConstrain (Var.layout var, ty), | |
240 | str " = "], | |
241 | indent (layoutExp exp, 3)] | |
242 | and layoutExp (Exp {decs, result}) = | |
243 | align [str "let", | |
244 | indent (align (List.map (decs, layoutDec)), 3), | |
245 | str "in", | |
246 | indent (VarExp.layout result, 3), | |
247 | str "end"] | |
248 | and layoutPrimExp e = | |
249 | case e of | |
250 | App {arg, func} => seq [VarExp.layout func, str " ", VarExp.layout arg] | |
251 | | Case {test, cases, default} => | |
252 | align [seq [str "case", | |
253 | case cases of Cases.Con _ => empty | |
254 | | Cases.Word (size, _) => str (WordSize.toString size), | |
255 | str " ", VarExp.layout test, str " of"], | |
256 | Cases.layout (cases, layoutExp), | |
257 | indent | |
258 | (align | |
259 | [case default of | |
260 | NONE => empty | |
261 | | SOME (e, _) => seq [str "_ => ", layoutExp e]], | |
262 | 2)] | |
263 | | ConApp {arg, con, targs, ...} => | |
264 | seq [str "new ", | |
265 | Con.layout con, | |
266 | layoutTargs targs, | |
267 | case arg of | |
268 | NONE => empty | |
269 | | SOME x => seq [str " ", VarExp.layout x]] | |
270 | | Const c => Const.layout c | |
271 | | Handle {catch, handler, try} => | |
272 | align [layoutExp try, | |
273 | seq [str "handle ", | |
274 | maybeConstrain (Var.layout (#1 catch), #2 catch), | |
275 | str " => ", layoutExp handler]] | |
276 | | Lambda l => layoutLambda l | |
277 | | PrimApp {args, prim, targs} => | |
278 | seq [str "prim ", | |
279 | Prim.layoutFull(prim, Type.layout), | |
280 | layoutTargs targs, | |
281 | str " ", tuple (Vector.toListMap (args, VarExp.layout))] | |
282 | | Profile e => ProfileExp.layout e | |
283 | | Raise {exn, extend} => | |
284 | seq [str "raise ", | |
285 | str (if extend then "extend " else ""), | |
286 | VarExp.layout exn] | |
287 | | Select {offset, tuple} => | |
288 | seq [str "#", Int.layout offset, str " ", VarExp.layout tuple] | |
289 | | Tuple xs => tuple (Vector.toList | |
290 | (Vector.mapi(xs, fn (i, x) => seq | |
291 | (* very specific case to prevent open comments *) | |
292 | [str (if i = 0 andalso | |
293 | (case x of (VarExp.T {var, ...}) => | |
294 | String.sub(Var.toString var, 0) = #"*") | |
295 | then " " | |
296 | else ""), | |
297 | VarExp.layout x]))) | |
298 | | Var x => VarExp.layout x | |
299 | and layoutLambda (Lam {arg, argType, body, mayInline, ...}) = | |
300 | align [seq [str "fn ", | |
301 | str (if not mayInline then "noinline " else ""), | |
302 | maybeConstrain (Var.layout arg, argType), | |
303 | str " => "], | |
304 | layoutExp body] | |
305 | ||
306 | end | |
307 | ||
308 | structure Dec = | |
309 | struct | |
310 | type exp = exp | |
311 | datatype t = datatype dec | |
312 | ||
313 | val layout = layoutDec | |
314 | end | |
315 | ||
316 | structure PrimExp = | |
317 | struct | |
318 | type exp = exp | |
319 | datatype t = datatype primExp | |
320 | ||
321 | val layout = layoutPrimExp | |
322 | end | |
323 | ||
324 | structure Exp = | |
325 | struct | |
326 | datatype t = datatype exp | |
327 | ||
328 | val layout = layoutExp | |
329 | val make = Exp | |
330 | fun dest (Exp r) = r | |
331 | val decs = #decs o dest | |
332 | val result = #result o dest | |
333 | ||
334 | fun fromPrimExp (exp: PrimExp.t, ty: Type.t): t = | |
335 | let val var = Var.newNoname () | |
336 | in Exp {decs = [Dec.MonoVal {var = var, ty = ty, exp = exp}], | |
337 | result = VarExp.mono var} | |
338 | end | |
339 | ||
340 | local | |
341 | fun make f (Exp {decs, result}, d) = | |
342 | Exp {decs = f (d, decs), | |
343 | result = result} | |
344 | in val prefix = make (op ::) | |
345 | val prefixs = make (op @) | |
346 | end | |
347 | ||
348 | fun enterLeave (e: t, ty: Type.t, si: SourceInfo.t): t = | |
349 | let | |
350 | datatype z = datatype Dec.t | |
351 | datatype z = datatype PrimExp.t | |
352 | fun prof f = | |
353 | MonoVal {exp = Profile (f si), | |
354 | ty = Type.unit, | |
355 | var = Var.newNoname ()} | |
356 | val exn = Var.newNoname () | |
357 | val res = Var.newNoname () | |
358 | val handler = | |
359 | make {decs = [prof ProfileExp.Leave, | |
360 | MonoVal {exp = Raise {exn = VarExp.mono exn, | |
361 | extend = false}, | |
362 | ty = ty, | |
363 | var = res}], | |
364 | result = VarExp.mono res} | |
365 | val touch = | |
366 | if !Control.profile = Control.ProfileCount | |
367 | then | |
368 | let | |
369 | val unit = Var.newNoname () | |
370 | in | |
371 | [MonoVal {exp = Tuple (Vector.new0 ()), | |
372 | ty = Type.unit, | |
373 | var = unit}, | |
374 | MonoVal | |
375 | {exp = PrimApp {args = Vector.new1 (VarExp.mono unit), | |
376 | prim = Prim.touch, | |
377 | targs = Vector.new1 Type.unit}, | |
378 | ty = Type.unit, | |
379 | var = Var.newNoname ()}] | |
380 | end | |
381 | else [] | |
382 | val {decs, result} = dest e | |
383 | val decs = | |
384 | List.concat [[prof ProfileExp.Enter], | |
385 | touch, | |
386 | decs, | |
387 | [prof ProfileExp.Leave]] | |
388 | val try = make {decs = decs, result = result} | |
389 | in | |
390 | fromPrimExp (Handle {catch = (exn, Type.exn), | |
391 | handler = handler, | |
392 | try = try}, | |
393 | ty) | |
394 | end | |
395 | ||
396 | (*------------------------------------*) | |
397 | (* foreach *) | |
398 | (*------------------------------------*) | |
399 | fun foreach {exp: t, | |
400 | handleExp: t -> unit, | |
401 | handlePrimExp: Var.t * Type.t * PrimExp.t -> unit, | |
402 | handleBoundVar: Var.t * Tyvar.t vector * Type.t -> unit, | |
403 | handleVarExp: VarExp.t -> unit}: unit = | |
404 | let | |
405 | fun monoVar (x, t) = handleBoundVar (x, Vector.new0 (), t) | |
406 | fun handleVarExps xs = Vector.foreach (xs, handleVarExp) | |
407 | fun loopExp e = | |
408 | let val {decs, result} = dest e | |
409 | in List.foreach (decs, loopDec) | |
410 | ; handleVarExp result | |
411 | ; handleExp e | |
412 | end | |
413 | and loopPrimExp (x: Var.t, ty: Type.t, e: PrimExp.t): unit = | |
414 | (handlePrimExp (x, ty, e) | |
415 | ; (case e of | |
416 | Const _ => () | |
417 | | Var x => handleVarExp x | |
418 | | Tuple xs => handleVarExps xs | |
419 | | Select {tuple, ...} => handleVarExp tuple | |
420 | | Lambda lambda => loopLambda lambda | |
421 | | PrimApp {args, ...} => handleVarExps args | |
422 | | Profile _ => () | |
423 | | ConApp {arg, ...} => (case arg of | |
424 | NONE => () | |
425 | | SOME x => handleVarExp x) | |
426 | | App {func, arg} => (handleVarExp func | |
427 | ; handleVarExp arg) | |
428 | | Raise {exn, ...} => handleVarExp exn | |
429 | | Handle {try, catch, handler, ...} => | |
430 | (loopExp try | |
431 | ; monoVar catch | |
432 | ; loopExp handler) | |
433 | | Case {test, cases, default} => | |
434 | (handleVarExp test | |
435 | ; Cases.foreach' (cases, loopExp, | |
436 | fn Pat.T {arg, ...} => | |
437 | case arg of | |
438 | NONE => () | |
439 | | SOME x => monoVar x) | |
440 | ; Option.app (default, loopExp o #1)))) | |
441 | and loopDec d = | |
442 | case d of | |
443 | MonoVal {var, ty, exp} => | |
444 | (monoVar (var, ty); loopPrimExp (var, ty, exp)) | |
445 | | PolyVal {var, tyvars, ty, exp} => | |
446 | (handleBoundVar (var, tyvars, ty) | |
447 | ; loopExp exp) | |
448 | | Exception _ => () | |
449 | | Fun {tyvars, decs, ...} => | |
450 | (Vector.foreach (decs, fn {ty, var, ...} => | |
451 | handleBoundVar (var, tyvars, ty)) | |
452 | ; Vector.foreach (decs, fn {lambda, ...} => | |
453 | loopLambda lambda)) | |
454 | and loopLambda (Lam {arg, argType, body, ...}): unit = | |
455 | (monoVar (arg, argType); loopExp body) | |
456 | in loopExp exp | |
457 | end | |
458 | ||
459 | fun ignore _ = () | |
460 | ||
461 | fun foreachPrimExp (e, f) = | |
462 | foreach {exp = e, | |
463 | handlePrimExp = f, | |
464 | handleExp = ignore, | |
465 | handleBoundVar = ignore, | |
466 | handleVarExp = ignore} | |
467 | ||
468 | fun foreachVarExp (e, f) = | |
469 | foreach {exp = e, | |
470 | handlePrimExp = ignore, | |
471 | handleExp = ignore, | |
472 | handleBoundVar = ignore, | |
473 | handleVarExp = f} | |
474 | ||
475 | fun foreachBoundVar (e, f) = | |
476 | foreach {exp = e, | |
477 | handlePrimExp = ignore, | |
478 | handleExp = ignore, | |
479 | handleBoundVar = f, | |
480 | handleVarExp = ignore} | |
481 | ||
482 | fun foreachExp (e, f) = | |
483 | foreach {exp = e, | |
484 | handlePrimExp = ignore, | |
485 | handleExp = f, | |
486 | handleBoundVar = ignore, | |
487 | handleVarExp = ignore} | |
488 | (* quell unused warning *) | |
489 | val _ = foreachExp | |
490 | ||
491 | fun hasPrim (e, f) = | |
492 | Exn.withEscape | |
493 | (fn escape => | |
494 | (foreachPrimExp (e, fn (_, _, e) => | |
495 | case e of | |
496 | PrimApp {prim, ...} => if f prim then escape true | |
497 | else () | |
498 | | _ => ()) | |
499 | ; false)) | |
500 | ||
501 | fun size e = | |
502 | let val n: int ref = ref 0 | |
503 | fun inc () = n := 1 + !n | |
504 | in foreachPrimExp (e, fn _ => inc ()); | |
505 | !n | |
506 | end | |
507 | val size = Trace.trace ("XmlTree.Exp.size", Layout.ignore, Int.layout) size | |
508 | (* quell unused warning *) | |
509 | val _ = size | |
510 | ||
511 | fun clear (e: t): unit = | |
512 | let open PrimExp | |
513 | fun clearTyvars ts = Vector.foreach (ts, Tyvar.clear) | |
514 | fun clearPat (Pat.T {arg, ...}) = | |
515 | case arg of | |
516 | NONE => () | |
517 | | SOME (x, _) => Var.clear x | |
518 | fun clearExp e = clearDecs (decs e) | |
519 | and clearDecs ds = List.foreach (ds, clearDec) | |
520 | and clearDec d = | |
521 | case d of | |
522 | MonoVal {var, exp, ...} => (Var.clear var; clearPrimExp exp) | |
523 | | PolyVal {var, tyvars, exp, ...} => | |
524 | (Var.clear var | |
525 | ; clearTyvars tyvars | |
526 | ; clearExp exp) | |
527 | | Fun {tyvars, decs} => | |
528 | (clearTyvars tyvars | |
529 | ; Vector.foreach (decs, fn {var, lambda, ...} => | |
530 | (Var.clear var | |
531 | ; clearLambda lambda))) | |
532 | | Exception {con, ...} => Con.clear con | |
533 | and clearPrimExp e = | |
534 | case e of | |
535 | Lambda l => clearLambda l | |
536 | | Case {cases, default, ...} => | |
537 | (Cases.foreach' (cases, clearExp, clearPat) | |
538 | ; Option.app (default, clearExp o #1)) | |
539 | | Handle {try, catch, handler, ...} => | |
540 | (clearExp try | |
541 | ; Var.clear (#1 catch) | |
542 | ; clearExp handler) | |
543 | | _ => () | |
544 | and clearLambda (Lam {arg, body, ...}) = | |
545 | (Var.clear arg; clearExp body) | |
546 | in clearExp e | |
547 | end | |
548 | end | |
549 | ||
550 | (*---------------------------------------------------*) | |
551 | (* Lambda *) | |
552 | (*---------------------------------------------------*) | |
553 | ||
554 | structure Lambda = | |
555 | struct | |
556 | type exp = exp | |
557 | datatype t = datatype lambda | |
558 | ||
559 | local | |
560 | fun make f (Lam r) = f r | |
561 | in | |
562 | val arg = make #arg | |
563 | val body = make #body | |
564 | val mayInline = make #mayInline | |
565 | end | |
566 | ||
567 | fun make {arg, argType, body, mayInline} = | |
568 | Lam {arg = arg, | |
569 | argType = argType, | |
570 | body = body, | |
571 | mayInline = mayInline, | |
572 | plist = PropertyList.new ()} | |
573 | ||
574 | fun dest (Lam {arg, argType, body, mayInline, ...}) = | |
575 | {arg = arg, argType = argType, body = body, mayInline = mayInline} | |
576 | ||
577 | fun plist (Lam {plist, ...}) = plist | |
578 | ||
579 | val layout = layoutLambda | |
580 | fun equals (f:t, f':t) = PropertyList.equals (plist f, plist f') | |
581 | end | |
582 | ||
583 | (* ------------------------------------------------- *) | |
584 | (* DirectExp *) | |
585 | (* ------------------------------------------------- *) | |
586 | structure DirectExp = | |
587 | struct | |
588 | open Dec PrimExp | |
589 | ||
590 | structure Cont = | |
591 | struct | |
592 | type t = PrimExp.t * Type.t -> Exp.t | |
593 | ||
594 | fun nameGen (k: VarExp.t * Type.t -> Exp.t): t = | |
595 | fn (e, t) => | |
596 | case e of | |
597 | Var x => k (x, t) | |
598 | | _ => let val x = Var.newNoname () | |
599 | in Exp.prefix (k (VarExp.mono x, t), | |
600 | MonoVal {var = x, ty = t, exp = e}) | |
601 | end | |
602 | ||
603 | fun name (k: VarExp.t * Type.t -> Exp.t): t = nameGen k | |
604 | ||
605 | val id: t = name (fn (x, _) => Exp {decs = [], result = x}) | |
606 | ||
607 | fun return (k: t, xt) = k xt | |
608 | end | |
609 | ||
610 | type t = Cont.t -> Exp.t | |
611 | ||
612 | fun send (e: t, k: Cont.t): Exp.t = e k | |
613 | ||
614 | fun toExp e = send (e, Cont.id) | |
615 | ||
616 | fun fromExp (Exp {decs, result}, ty): t = | |
617 | fn k => Exp.prefixs (k (Var result, ty), decs) | |
618 | ||
619 | fun sendName (e, k) = send (e, Cont.name k) | |
620 | ||
621 | fun simple (e: PrimExp.t * Type.t) k = Cont.return (k, e) | |
622 | ||
623 | fun const c = simple (Const c, Type.ofConst c) | |
624 | ||
625 | val string = const o Const.string | |
626 | ||
627 | fun varExp (x, t) = simple (Var x, t) | |
628 | ||
629 | fun var {var, targs, ty} = | |
630 | varExp (VarExp.T {var = var, targs = targs}, ty) | |
631 | ||
632 | fun monoVar (x, t) = var {var = x, targs = Vector.new0 (), ty = t} | |
633 | ||
634 | fun convertsGen (es: t vector, | |
635 | k: (VarExp.t * Type.t) vector -> Exp.t): Exp.t = | |
636 | let | |
637 | val n = Vector.length es | |
638 | fun loop (i, xs) = | |
639 | if i = n | |
640 | then k (Vector.fromListRev xs) | |
641 | else sendName (Vector.sub (es, i), | |
642 | fn x => loop (i + 1, x :: xs)) | |
643 | in loop (0, []) | |
644 | end | |
645 | ||
646 | fun converts (es: t vector, | |
647 | make: (VarExp.t * Type.t) vector -> PrimExp.t * Type.t): t = | |
648 | fn k => convertsGen (es, k o make) | |
649 | ||
650 | fun convert (e: t, make: VarExp.t * Type.t -> PrimExp.t * Type.t): t = | |
651 | fn k => send (e, Cont.name (k o make)) | |
652 | ||
653 | fun convertOpt (e, make) = | |
654 | case e of | |
655 | NONE => simple (make NONE) | |
656 | | SOME e => convert (e, make o SOME o #1) | |
657 | ||
658 | fun tuple {exps: t vector, ty: Type.t}: t = | |
659 | if 1 = Vector.length exps | |
660 | then Vector.first exps | |
661 | else converts (exps, fn xs => | |
662 | (PrimExp.Tuple (Vector.map (xs, #1)), ty)) | |
663 | ||
664 | fun select {tuple, offset, ty} = | |
665 | convert (tuple, fn (tuple, _) => | |
666 | (Select {tuple = tuple, offset = offset}, ty)) | |
667 | ||
668 | fun conApp {con, targs, arg, ty} = | |
669 | convertOpt (arg, fn arg => | |
670 | (ConApp {con = con, targs = targs, arg = arg}, ty)) | |
671 | ||
672 | local | |
673 | fun make c () = | |
674 | conApp {con = c, | |
675 | targs = Vector.new0 (), | |
676 | arg = NONE, | |
677 | ty = Type.bool} | |
678 | in | |
679 | val truee = make Con.truee | |
680 | val falsee = make Con.falsee | |
681 | end | |
682 | ||
683 | fun primApp {prim, targs, args, ty} = | |
684 | converts (args, fn args => | |
685 | (PrimApp {prim = prim, | |
686 | targs = targs, | |
687 | args = Vector.map (args, #1)}, | |
688 | ty)) | |
689 | ||
690 | fun convert2 (e1, e2, make) = | |
691 | converts (Vector.new2 (e1, e2), | |
692 | fn xs => make (Vector.first xs, Vector.sub (xs, 1))) | |
693 | ||
694 | fun app {func, arg, ty} = | |
695 | convert2 (func, arg, fn ((func, _), (arg, _)) => | |
696 | (App {func = func, arg = arg}, ty)) | |
697 | ||
698 | fun casee {test, cases, default, ty} = | |
699 | convert (test, fn (test, _) => | |
700 | (Case | |
701 | {test = test, | |
702 | cases = Cases.map (cases, toExp), | |
703 | default = (Option.map | |
704 | (default, fn (e, r) => (toExp e, r)))}, | |
705 | ty)) | |
706 | ||
707 | fun raisee {exn: t, extend: bool, ty: Type.t}: t = | |
708 | convert (exn, fn (x, _) => (Raise {exn = x, extend = extend}, ty)) | |
709 | ||
710 | fun handlee {try, catch, handler, ty} = | |
711 | simple (Handle {try = toExp try, | |
712 | catch = catch, | |
713 | handler = toExp handler}, | |
714 | ty) | |
715 | ||
716 | fun unit () = tuple {exps = Vector.new0 (), ty = Type.unit} | |
717 | ||
718 | fun reff (e: t): t = | |
719 | convert (e, fn (x, t) => | |
720 | (PrimApp {prim = Prim.reff, | |
721 | targs = Vector.new1 t, | |
722 | args = Vector.new1 x}, | |
723 | Type.reff t)) | |
724 | ||
725 | fun deref (e: t): t = | |
726 | convert (e, fn (x, t) => | |
727 | let | |
728 | val t = Type.deRef t | |
729 | in | |
730 | (PrimApp {prim = Prim.deref, | |
731 | targs = Vector.new1 t, | |
732 | args = Vector.new1 x}, | |
733 | t) | |
734 | end) | |
735 | ||
736 | fun vectorLength (e: t): t = | |
737 | convert (e, fn (x, t) => | |
738 | let | |
739 | val t = Type.deVector t | |
740 | in | |
741 | (PrimApp {prim = Prim.vectorLength, | |
742 | targs = Vector.new1 t, | |
743 | args = Vector.new1 x}, | |
744 | Type.word (WordSize.seqIndex ())) | |
745 | end) | |
746 | ||
747 | fun vectorSub (e1: t, e2: t): t = | |
748 | convert2 (e1, e2, fn ((x1, t1), (x2, _)) => | |
749 | let | |
750 | val t = Type.deVector t1 | |
751 | in | |
752 | (PrimApp {prim = Prim.vectorSub, | |
753 | targs = Vector.new1 t, | |
754 | args = Vector.new2 (x1, x2)}, | |
755 | t) | |
756 | end) | |
757 | ||
758 | fun equal (e1, e2) = | |
759 | convert2 (e1, e2, fn ((x1, t), (x2, _)) => | |
760 | (PrimApp {prim = Prim.equal, | |
761 | targs = Vector.new1 t, | |
762 | args = Vector.new2 (x1, x2)}, | |
763 | Type.bool)) | |
764 | ||
765 | fun iff {test, thenn, elsee, ty} = | |
766 | casee {test = test, | |
767 | cases = Cases.Con (Vector.new2 ((Pat.truee, thenn), | |
768 | (Pat.falsee, elsee))), | |
769 | default = NONE, | |
770 | ty = ty} | |
771 | ||
772 | fun vall {var, exp}: Dec.t list = | |
773 | let val t = ref Type.unit | |
774 | val Exp {decs, result} = | |
775 | sendName (exp, fn (x, t') => (t := t'; | |
776 | Exp {decs = [], result = x})) | |
777 | in decs @ [MonoVal {var = var, ty = !t, exp = Var result}] | |
778 | end | |
779 | ||
780 | fun sequence es = | |
781 | converts (es, fn xs => let val (x, t) = Vector.last xs | |
782 | in (Var x, t) | |
783 | end) | |
784 | ||
785 | val bug: string -> t = | |
786 | fn s => | |
787 | primApp {prim = Prim.bug, | |
788 | targs = Vector.new0 (), | |
789 | args = Vector.new1 (string s), | |
790 | ty = Type.unit} | |
791 | ||
792 | fun seq (es, make) = | |
793 | fn k => convertsGen (es, fn xts => | |
794 | send (make (Vector.map (xts, varExp)), k)) | |
795 | ||
796 | fun lett {decs, body} = fn k => Exp.prefixs (send (body, k), decs) | |
797 | ||
798 | fun let1 {var, exp, body} = | |
799 | fn k => | |
800 | send (exp, fn (exp, ty) => | |
801 | Exp.prefix (send (body, k), | |
802 | Dec.MonoVal {var = var, ty = ty, exp = exp})) | |
803 | ||
804 | fun lambda {arg, argType, body, bodyType, mayInline} = | |
805 | simple (Lambda (Lambda.make {arg = arg, | |
806 | argType = argType, | |
807 | body = toExp body, | |
808 | mayInline = mayInline}), | |
809 | Type.arrow (argType, bodyType)) | |
810 | ||
811 | fun fromLambda (l, ty) = | |
812 | simple (Lambda l, ty) | |
813 | ||
814 | fun detupleGen (e: PrimExp.t, | |
815 | t: Type.t, | |
816 | components: Var.t vector, | |
817 | body: Exp.t): Exp.t = | |
818 | Exp.prefixs | |
819 | (body, | |
820 | case Vector.length components of | |
821 | 0 => [] | |
822 | | 1 => [MonoVal {var = Vector.first components, ty = t, exp = e}] | |
823 | | _ => | |
824 | let | |
825 | val ts = Type.deTuple t | |
826 | val tupleVar = Var.newNoname () | |
827 | in MonoVal {var = tupleVar, ty = t, exp = e} | |
828 | :: | |
829 | #2 (Vector.fold2 | |
830 | (components, ts, (0, []), | |
831 | fn (x, t, (i, ac)) => | |
832 | (i + 1, | |
833 | MonoVal {var = x, ty = t, | |
834 | exp = Select {tuple = VarExp.mono tupleVar, | |
835 | offset = i}} | |
836 | :: ac))) | |
837 | end) | |
838 | ||
839 | fun detupleBind {tuple, components, body} = | |
840 | fn k => send (tuple, fn (e, t) => detupleGen (e, t, components, body k)) | |
841 | ||
842 | fun detuple {tuple: t, body}: t = | |
843 | fn k => | |
844 | tuple | |
845 | (fn (e, t) => | |
846 | let | |
847 | val ts = Type.deTuple t | |
848 | in | |
849 | case e of | |
850 | Tuple xs => send (body (Vector.zip (xs, ts)), k) | |
851 | | _ => let | |
852 | val components = | |
853 | Vector.map (ts, fn _ => Var.newNoname ()) | |
854 | in | |
855 | detupleGen (e, t, components, | |
856 | send (body (Vector.map2 | |
857 | (components, ts, fn (x, t) => | |
858 | (VarExp.mono x, t))), | |
859 | k)) | |
860 | end | |
861 | end) | |
862 | ||
863 | fun devector {vector: t, length: int, body}: t = | |
864 | fn k => | |
865 | let | |
866 | val es = | |
867 | Vector.tabulate | |
868 | (length, fn i => | |
869 | vectorSub (vector, const (Const.word (WordX.fromIntInf (IntInf.fromInt i, WordSize.seqIndex ()))))) | |
870 | in | |
871 | convertsGen (es, fn args => (body args) k) | |
872 | end | |
873 | end | |
874 | ||
875 | (*---------------------------------------------------*) | |
876 | (* Datatype *) | |
877 | (*---------------------------------------------------*) | |
878 | ||
879 | structure Datatype = | |
880 | struct | |
881 | type t = {cons: {arg: Type.t option, | |
882 | con: Con.t} vector, | |
883 | tycon: Tycon.t, | |
884 | tyvars: Tyvar.t vector} | |
885 | ||
886 | fun layout ({cons, tycon, tyvars}: t): Layout.t = | |
887 | let | |
888 | open Layout | |
889 | in | |
890 | seq [layoutTyvars tyvars, | |
891 | Tycon.layout tycon, str " = ", | |
892 | align | |
893 | (separateLeft (Vector.toListMap (cons, layoutConArg), | |
894 | "| "))] | |
895 | end | |
896 | end | |
897 | ||
898 | (*---------------------------------------------------*) | |
899 | (* Program *) | |
900 | (*---------------------------------------------------*) | |
901 | ||
902 | structure Program = | |
903 | struct | |
904 | datatype t = T of {body: Exp.t, | |
905 | datatypes: Datatype.t vector, | |
906 | overflow: Var.t option} | |
907 | ||
908 | fun layout (T {body, datatypes, overflow, ...}) = | |
909 | let | |
910 | open Layout | |
911 | in | |
912 | align [str "\n\nDatatypes:", | |
913 | align (Vector.toListMap (datatypes, Datatype.layout)), | |
914 | seq [str "\n\nOverflow: ", Option.layout Var.layout overflow], | |
915 | str "\n\nBody:", | |
916 | Exp.layout body] | |
917 | end | |
918 | ||
919 | fun layouts (T {body, datatypes, overflow, ...}, output') = | |
920 | let | |
921 | open Layout | |
922 | (* Layout includes an output function, so we need to rebind output | |
923 | * to the one above. | |
924 | *) | |
925 | val output = output' | |
926 | in | |
927 | output (str "\n\nDatatypes:") | |
928 | ; Vector.foreach (datatypes, output o Datatype.layout) | |
929 | ; output (seq [str "\n\nOverflow: ", Option.layout Var.layout overflow]) | |
930 | ; output (str "\n\nBody:") | |
931 | ; output (Exp.layout body) | |
932 | end | |
933 | ||
934 | fun clear (T {datatypes, body, ...}) = | |
935 | (Vector.foreach (datatypes, fn {tycon, tyvars, cons} => | |
936 | (Tycon.clear tycon | |
937 | ; Vector.foreach (tyvars, Tyvar.clear) | |
938 | ; Vector.foreach (cons, Con.clear o #con))) | |
939 | ; Exp.clear body) | |
940 | ||
941 | fun layoutStats (T {datatypes, body, ...}) = | |
942 | let | |
943 | val numTypes = ref 0 | |
944 | fun inc _ = numTypes := 1 + !numTypes | |
945 | val {hom, destroy} = Type.makeHom {var = inc, con = inc} | |
946 | val numPrimExps = ref 0 | |
947 | open Layout | |
948 | in | |
949 | Vector.foreach (datatypes, fn {cons, ...} => | |
950 | Vector.foreach (cons, fn {arg, ...} => | |
951 | case arg of | |
952 | NONE => () | |
953 | | SOME t => hom t)) | |
954 | ; (Exp.foreach | |
955 | {exp = body, | |
956 | handlePrimExp = fn _ => numPrimExps := 1 + !numPrimExps, | |
957 | handleVarExp = fn _ => (), | |
958 | handleBoundVar = hom o #3, | |
959 | handleExp = fn _ => ()}) | |
960 | ; destroy () | |
961 | ; align [seq [str "num primexps in program = ", Int.layout (!numPrimExps)], | |
962 | seq [str "num types in program = ", Int.layout (!numTypes)], | |
963 | Type.stats ()] | |
964 | end | |
965 | end | |
966 | ||
967 | end |