Mercurial > urweb
comparison src/monoize.sml @ 252:7e9bd70ad3ce
Monoized and optimized initial query test
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Sun, 31 Aug 2008 13:58:47 -0400 |
parents | 326fb4686f60 |
children | 7f6620853c36 |
comparison
equal
deleted
inserted
replaced
251:326fb4686f60 | 252:7e9bd70ad3ce |
---|---|
35 | 35 |
36 structure IM = IntBinaryMap | 36 structure IM = IntBinaryMap |
37 | 37 |
38 val dummyTyp = (L'.TDatatype (0, ref (L'.Enum, [])), E.dummySpan) | 38 val dummyTyp = (L'.TDatatype (0, ref (L'.Enum, [])), E.dummySpan) |
39 | 39 |
40 structure U = MonoUtil | |
41 | |
42 val liftExpInExp = | |
43 U.Exp.mapB {typ = fn t => t, | |
44 exp = fn bound => fn e => | |
45 case e of | |
46 L'.ERel xn => | |
47 if xn < bound then | |
48 e | |
49 else | |
50 L'.ERel (xn + 1) | |
51 | _ => e, | |
52 bind = fn (bound, U.Exp.RelE _) => bound + 1 | |
53 | (bound, _) => bound} | |
54 | |
40 fun monoName env (all as (c, loc)) = | 55 fun monoName env (all as (c, loc)) = |
41 let | 56 let |
42 fun poly () = | 57 fun poly () = |
43 (E.errorAt loc "Unsupported name constructor"; | 58 (E.errorAt loc "Unsupported name constructor"; |
44 Print.eprefaces' [("Constructor", CorePrint.p_con env all)]; | 59 Print.eprefaces' [("Constructor", CorePrint.p_con env all)]; |
69 (L'.TFfi ("Basis", "string"), loc) | 84 (L'.TFfi ("Basis", "string"), loc) |
70 | L.CApp ((L.CApp ((L.CFfi ("Basis", "xhtml"), _), _), _), _) => | 85 | L.CApp ((L.CApp ((L.CFfi ("Basis", "xhtml"), _), _), _), _) => |
71 (L'.TFfi ("Basis", "string"), loc) | 86 (L'.TFfi ("Basis", "string"), loc) |
72 | 87 |
73 | L.CApp ((L.CFfi ("Basis", "transaction"), _), t) => | 88 | L.CApp ((L.CFfi ("Basis", "transaction"), _), t) => |
74 (L'.TFun (mt env dtmap t, (L'.TRecord [], loc)), loc) | 89 (L'.TFun ((L'.TRecord [], loc), mt env dtmap t), loc) |
90 | L.CApp ((L.CFfi ("Basis", "sql_table"), _), _) => | |
91 (L'.TFfi ("Basis", "string"), loc) | |
92 | L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_query"), _), _), _), _) => | |
93 (L'.TFfi ("Basis", "string"), loc) | |
94 | L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_query1"), _), _), _), _), _), _) => | |
95 (L'.TFfi ("Basis", "string"), loc) | |
96 | L.CApp ((L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_exp"), _), _), _), _), _), _), _), _) => | |
97 (L'.TFfi ("Basis", "string"), loc) | |
98 | |
99 | L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_subset"), _), _), _), _) => | |
100 (L'.TRecord [], loc) | |
101 | L.CFfi ("Basis", "sql_relop") => | |
102 (L'.TFfi ("Basis", "string"), loc) | |
103 | L.CFfi ("Basis", "sql_direction") => | |
104 (L'.TFfi ("Basis", "string"), loc) | |
105 | L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_order_by"), _), _), _), _) => | |
106 (L'.TFfi ("Basis", "string"), loc) | |
107 | L.CFfi ("Basis", "sql_limit") => | |
108 (L'.TFfi ("Basis", "string"), loc) | |
109 | L.CFfi ("Basis", "sql_offset") => | |
110 (L'.TFfi ("Basis", "string"), loc) | |
111 | |
112 | L.CApp ((L.CFfi ("Basis", "sql_injectable"), _), t) => | |
113 (L'.TFun (mt env dtmap t, (L'.TFfi ("Basis", "string"), loc)), loc) | |
114 | L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_unary"), _), _), _), _) => | |
115 (L'.TFfi ("Basis", "string"), loc) | |
116 | L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_binary"), _), _), _), _), _), _) => | |
117 (L'.TFfi ("Basis", "string"), loc) | |
118 | L.CFfi ("Basis", "sql_comparison") => | |
119 (L'.TFfi ("Basis", "string"), loc) | |
120 | L.CApp ((L.CFfi ("Basis", "sql_aggregate"), _), t) => | |
121 (L'.TFfi ("Basis", "string"), loc) | |
122 | L.CApp ((L.CFfi ("Basis", "sql_summable"), _), _) => | |
123 (L'.TRecord [], loc) | |
124 | L.CApp ((L.CFfi ("Basis", "sql_maxable"), _), _) => | |
125 (L'.TRecord [], loc) | |
75 | 126 |
76 | L.CRel _ => poly () | 127 | L.CRel _ => poly () |
77 | L.CNamed n => | 128 | L.CNamed n => |
78 (case IM.find (dtmap, n) of | 129 (case IM.find (dtmap, n) of |
79 SOME r => (L'.TDatatype (n, r), loc) | 130 SOME r => (L'.TDatatype (n, r), loc) |
345 | L.PCon (dk, pc, [], po) => (L'.PCon (dk, monoPatCon env pc, Option.map (monoPat env) po), loc) | 396 | L.PCon (dk, pc, [], po) => (L'.PCon (dk, monoPatCon env pc, Option.map (monoPat env) po), loc) |
346 | L.PCon _ => poly () | 397 | L.PCon _ => poly () |
347 | L.PRecord xps => (L'.PRecord (map (fn (x, p, t) => (x, monoPat env p, monoType env t)) xps), loc) | 398 | L.PRecord xps => (L'.PRecord (map (fn (x, p, t) => (x, monoPat env p, monoType env t)) xps), loc) |
348 end | 399 end |
349 | 400 |
401 fun strcat loc es = | |
402 case es of | |
403 [] => (L'.EPrim (Prim.String ""), loc) | |
404 | [e] => e | |
405 | _ => | |
406 let | |
407 val e2 = List.last es | |
408 val es = List.take (es, length es - 1) | |
409 val e1 = List.last es | |
410 val es = List.take (es, length es - 1) | |
411 in | |
412 foldr (fn (e, e') => (L'.EStrcat (e, e'), loc)) | |
413 (L'.EStrcat (e1, e2), loc) es | |
414 end | |
415 | |
416 fun strcatComma loc es = | |
417 case es of | |
418 [] => (L'.EPrim (Prim.String ""), loc) | |
419 | [e] => e | |
420 | _ => | |
421 let | |
422 val e1 = List.last es | |
423 val es = List.take (es, length es - 1) | |
424 in | |
425 foldr (fn (e, e') => | |
426 case e of | |
427 (L'.EPrim (Prim.String ""), _) => e' | |
428 | _ => | |
429 (L'.EStrcat (e, | |
430 (L'.EStrcat ((L'.EPrim (Prim.String ", "), loc), e'), loc)), loc)) | |
431 e1 es | |
432 end | |
433 | |
434 fun strcatR loc e xs = strcatComma loc (map (fn (x, _) => (L'.EField (e, x), loc)) xs) | |
435 | |
350 fun monoExp (env, st, fm) (all as (e, loc)) = | 436 fun monoExp (env, st, fm) (all as (e, loc)) = |
351 let | 437 let |
352 fun poly () = | 438 fun poly () = |
353 (E.errorAt loc "Unsupported expression"; | 439 (E.errorAt loc "Unsupported expression"; |
354 Print.eprefaces' [("Expression", CorePrint.p_exp env all)]; | 440 Print.eprefaces' [("Expression", CorePrint.p_exp env all)]; |
371 end | 457 end |
372 in | 458 in |
373 ((L'.ECon (dk, monoPatCon env pc, eo), loc), fm) | 459 ((L'.ECon (dk, monoPatCon env pc, eo), loc), fm) |
374 end | 460 end |
375 | L.ECon _ => poly () | 461 | L.ECon _ => poly () |
376 | L.EFfi mx => ((L'.EFfi mx, loc), fm) | |
377 | L.EFfiApp (m, x, es) => | |
378 let | |
379 val (es, fm) = ListUtil.foldlMap (fn (e, fm) => monoExp (env, st, fm) e) fm es | |
380 in | |
381 ((L'.EFfiApp (m, x, es), loc), fm) | |
382 end | |
383 | 462 |
384 | L.ECApp ((L.EFfi ("Basis", "return"), _), t) => | 463 | L.ECApp ((L.EFfi ("Basis", "return"), _), t) => |
385 ((L'.EAbs ("x", monoType env t, (L'.TRecord [], loc), (L'.ERel 0, loc)), loc), fm) | 464 let |
465 val t = monoType env t | |
466 in | |
467 ((L'.EAbs ("x", t, | |
468 (L'.TFun ((L'.TRecord [], loc), t), loc), | |
469 (L'.EAbs ("_", (L'.TRecord [], loc), t, | |
470 (L'.ERel 1, loc)), loc)), loc), fm) | |
471 end | |
386 | L.ECApp ((L.ECApp ((L.EFfi ("Basis", "bind"), _), t1), _), t2) => | 472 | L.ECApp ((L.ECApp ((L.EFfi ("Basis", "bind"), _), t1), _), t2) => |
387 let | 473 let |
388 val t1 = monoType env t1 | 474 val t1 = monoType env t1 |
389 val t2 = monoType env t2 | 475 val t2 = monoType env t2 |
390 val un = (L'.TRecord [], loc) | 476 val un = (L'.TRecord [], loc) |
391 val mt1 = (L'.TFun (t1, un), loc) | 477 val mt1 = (L'.TFun (un, t1), loc) |
392 val mt2 = (L'.TFun (t2, un), loc) | 478 val mt2 = (L'.TFun (un, t2), loc) |
393 in | 479 in |
394 ((L'.EAbs ("m1", mt1, (L'.TFun (mt1, (L'.TFun (mt2, un), loc)), loc), | 480 ((L'.EAbs ("m1", mt1, (L'.TFun (mt1, (L'.TFun (mt2, (L'.TFun (un, un), loc)), loc)), loc), |
395 (L'.EAbs ("m2", mt2, un, | 481 (L'.EAbs ("m2", mt2, (L'.TFun (un, un), loc), |
396 (L'.ELet ("r", t1, (L'.ERel 1, loc), | 482 (L'.EAbs ("_", un, un, |
397 (L'.EApp ((L'.ERel 1, loc), (L'.ERel 0, loc)), | 483 (L'.ELet ("r", t1, (L'.EApp ((L'.ERel 2, loc), |
398 loc)), loc)), loc)), loc), | 484 (L'.ERecord [], loc)), loc), |
485 (L'.EApp ( | |
486 (L'.EApp ((L'.ERel 2, loc), (L'.ERel 0, loc)), loc), | |
487 (L'.ERecord [], loc)), | |
488 loc)), loc)), loc)), loc)), loc), | |
399 fm) | 489 fm) |
400 end | 490 end |
401 | 491 |
492 | L.ECApp ( | |
493 (L.ECApp ( | |
494 (L.ECApp ((L.EFfi ("Basis", "query"), _), (L.CRecord (_, tables), _)), _), | |
495 exps), _), | |
496 state) => | |
497 (case monoType env (L.TRecord exps, loc) of | |
498 (L'.TRecord exps, _) => | |
499 let | |
500 val tables = map (fn ((L.CName x, _), xts) => | |
501 (case monoType env (L.TRecord xts, loc) of | |
502 (L'.TRecord xts, _) => SOME (x, xts) | |
503 | _ => NONE) | |
504 | _ => NONE) tables | |
505 in | |
506 if List.exists (fn x => x = NONE) tables then | |
507 poly () | |
508 else | |
509 let | |
510 val tables = List.mapPartial (fn x => x) tables | |
511 val state = monoType env state | |
512 val s = (L'.TFfi ("Basis", "string"), loc) | |
513 val un = (L'.TRecord [], loc) | |
514 | |
515 val rt = exps @ map (fn (x, xts) => (x, (L'.TRecord xts, loc))) tables | |
516 val ft = (L'.TFun ((L'.TRecord rt, loc), | |
517 (L'.TFun (state, | |
518 (L'.TFun (un, state), loc)), | |
519 loc)), loc) | |
520 | |
521 val body' = (L'.EAbs ("r", (L'.TRecord rt, loc), | |
522 (L'.TFun (state, state), loc), | |
523 (L'.EAbs ("acc", state, state, | |
524 (L'.EApp ( | |
525 (L'.EApp ( | |
526 (L'.EApp ((L'.ERel 4, loc), | |
527 (L'.ERel 1, loc)), loc), | |
528 (L'.ERel 0, loc)), loc), | |
529 (L'.ERecord [], loc)), loc)), loc)), loc) | |
530 | |
531 val body = (L'.EQuery {exps = exps, | |
532 tables = tables, | |
533 state = state, | |
534 query = (L'.ERel 3, loc), | |
535 body = body', | |
536 initial = (L'.ERel 1, loc)}, | |
537 loc) | |
538 in | |
539 ((L'.EAbs ("q", s, (L'.TFun (ft, (L'.TFun (state, (L'.TFun (un, state), loc)), loc)), loc), | |
540 (L'.EAbs ("f", ft, (L'.TFun (state, (L'.TFun (un, state), loc)), loc), | |
541 (L'.EAbs ("i", state, (L'.TFun (un, state), loc), | |
542 (L'.EAbs ("_", un, state, | |
543 body), loc)), loc)), loc)), loc), fm) | |
544 end | |
545 end | |
546 | _ => poly ()) | |
547 | |
548 | L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_query"), _), _), _), _), _), _) => | |
549 let | |
550 fun sc s = (L'.EPrim (Prim.String s), loc) | |
551 val s = (L'.TFfi ("Basis", "string"), loc) | |
552 fun gf s = (L'.EField ((L'.ERel 0, loc), s), loc) | |
553 in | |
554 ((L'.EAbs ("r", | |
555 (L'.TRecord [("Rows", s), ("OrderBy", s), ("Limit", s), ("Offset", s)], loc), | |
556 s, | |
557 strcat loc [gf "Rows", | |
558 gf "OrderBy", | |
559 gf "Limit", | |
560 gf "Offset"]), loc), fm) | |
561 end | |
562 | |
563 | L.ECApp ( | |
564 (L.ECApp ( | |
565 (L.ECApp ( | |
566 (L.ECApp ( | |
567 (L.EFfi ("Basis", "sql_query1"), _), | |
568 (L.CRecord (_, tables), _)), _), | |
569 (L.CRecord (_, grouped), _)), _), | |
570 (L.CRecord (_, stables), _)), _), | |
571 sexps) => | |
572 let | |
573 fun sc s = (L'.EPrim (Prim.String s), loc) | |
574 val s = (L'.TFfi ("Basis", "string"), loc) | |
575 val un = (L'.TRecord [], loc) | |
576 fun gf s = (L'.EField ((L'.ERel 0, loc), s), loc) | |
577 | |
578 fun doTables tables = | |
579 let | |
580 val tables = map (fn ((L.CName x, _), xts) => | |
581 (case monoType env (L.TRecord xts, loc) of | |
582 (L'.TRecord xts, _) => SOME (x, xts) | |
583 | _ => NONE) | |
584 | _ => NONE) tables | |
585 in | |
586 if List.exists (fn x => x = NONE) tables then | |
587 NONE | |
588 else | |
589 SOME (List.mapPartial (fn x => x) tables) | |
590 end | |
591 in | |
592 case (doTables tables, doTables grouped, doTables stables, monoType env (L.TRecord sexps, loc)) of | |
593 (SOME tables, SOME grouped, SOME stables, (L'.TRecord sexps, _)) => | |
594 ((L'.EAbs ("r", | |
595 (L'.TRecord [("From", (L'.TRecord (map (fn (x, _) => (x, s)) tables), loc)), | |
596 ("Where", s), | |
597 ("GroupBy", un), | |
598 ("Having", s), | |
599 ("SelectFields", un), | |
600 ("SelectExps", (L'.TRecord (map (fn (x, _) => (x, s)) sexps), loc))], | |
601 loc), | |
602 s, | |
603 strcat loc [sc "SELECT ", | |
604 strcatR loc (gf "SelectExps") sexps, | |
605 case sexps of | |
606 [] => sc "" | |
607 | _ => sc ", ", | |
608 strcatComma loc (map (fn (x, xts) => | |
609 strcatComma loc | |
610 (map (fn (x', _) => | |
611 sc (x ^ "." ^ x')) | |
612 xts)) stables), | |
613 sc " FROM ", | |
614 strcatComma loc (map (fn (x, _) => strcat loc [(L'.EField (gf "From", x), loc), | |
615 sc (" AS " ^ x)]) tables) | |
616 ]), loc), | |
617 fm) | |
618 | _ => poly () | |
619 end | |
620 | |
621 | L.ECApp ( | |
622 (L.ECApp ( | |
623 (L.ECApp ( | |
624 (L.ECApp ( | |
625 (L.EFfi ("Basis", "sql_inject"), _), | |
626 _), _), | |
627 _), _), | |
628 _), _), | |
629 t) => | |
630 let | |
631 val t = monoType env t | |
632 val s = (L'.TFfi ("Basis", "string"), loc) | |
633 in | |
634 ((L'.EAbs ("f", (L'.TFun (t, s), loc), (L'.TFun (t, s), loc), | |
635 (L'.ERel 0, loc)), loc), fm) | |
636 end | |
637 | |
638 | L.ECApp ((L.EFfi ("Basis", "sql_subset"), _), _) => | |
639 ((L'.ERecord [], loc), fm) | |
640 | L.ECApp ((L.EFfi ("Basis", "sql_subset_all"), _), _) => | |
641 ((L'.ERecord [], loc), fm) | |
642 | |
643 | L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_order_by_Nil"), _), _), _), _) => | |
644 ((L'.EPrim (Prim.String ""), loc), fm) | |
645 | |
646 | L.EFfi ("Basis", "sql_no_limit") => | |
647 ((L'.EPrim (Prim.String ""), loc), fm) | |
648 | L.EFfi ("Basis", "sql_no_offset") => | |
649 ((L'.EPrim (Prim.String ""), loc), fm) | |
650 | |
402 | L.EApp ( | 651 | L.EApp ( |
403 (L.ECApp ( | 652 (L.ECApp ( |
404 (L.ECApp ((L.EFfi ("Basis", "cdata"), _), _), _), | 653 (L.ECApp ((L.EFfi ("Basis", "cdata"), _), _), _), |
405 _), _), | 654 _), _), |
406 se) => | 655 se) => |
719 ((L'.EAbs (x, monoType env dom, monoType env ran, e), loc), fm) | 968 ((L'.EAbs (x, monoType env dom, monoType env ran, e), loc), fm) |
720 end | 969 end |
721 | L.ECApp _ => poly () | 970 | L.ECApp _ => poly () |
722 | L.ECAbs _ => poly () | 971 | L.ECAbs _ => poly () |
723 | 972 |
973 | L.EFfi mx => ((L'.EFfi mx, loc), fm) | |
974 | L.EFfiApp (m, x, es) => | |
975 let | |
976 val (es, fm) = ListUtil.foldlMap (fn (e, fm) => monoExp (env, st, fm) e) fm es | |
977 in | |
978 ((L'.EFfiApp (m, x, es), loc), fm) | |
979 end | |
980 | |
724 | L.ERecord xes => | 981 | L.ERecord xes => |
725 let | 982 let |
726 val (xes, fm) = ListUtil.foldlMap | 983 val (xes, fm) = ListUtil.foldlMap |
727 (fn ((x, e, t), fm) => | 984 (fn ((x, e, t), fm) => |
728 let | 985 let |
760 | 1017 |
761 | L.EWrite e => | 1018 | L.EWrite e => |
762 let | 1019 let |
763 val (e, fm) = monoExp (env, st, fm) e | 1020 val (e, fm) = monoExp (env, st, fm) e |
764 in | 1021 in |
765 ((L'.EWrite e, loc), fm) | 1022 ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TRecord [], loc), |
1023 (L'.EWrite (liftExpInExp 0 e), loc)), loc), fm) | |
766 end | 1024 end |
767 | 1025 |
768 | L.EClosure (n, es) => | 1026 | L.EClosure (n, es) => |
769 let | 1027 let |
770 val (es, fm) = ListUtil.foldlMap (fn (e, fm) => | 1028 val (es, fm) = ListUtil.foldlMap (fn (e, fm) => |