comparison src/jscomp.sml @ 591:8f8771f32909

Injecting a float
author Adam Chlipala <adamc@hcoop.net>
date Thu, 01 Jan 2009 15:59:02 -0500
parents 57f476c934da
children a8be5a2068a5
comparison
equal deleted inserted replaced
590:57f476c934da 591:8f8771f32909
94 | EJavaScript _ => 0 94 | EJavaScript _ => 0
95 | ESignalReturn e => varDepth e 95 | ESignalReturn e => varDepth e
96 | ESignalBind (e1, e2) => Int.max (varDepth e1, varDepth e2) 96 | ESignalBind (e1, e2) => Int.max (varDepth e1, varDepth e2)
97 | ESignalSource e => varDepth e 97 | ESignalSource e => varDepth e
98 98
99 fun closedUpto d =
100 let
101 fun cu inner (e, _) =
102 case e of
103 EPrim _ => true
104 | ERel n => n < inner orelse n - inner >= d
105 | ENamed _ => true
106 | ECon (_, _, NONE) => true
107 | ECon (_, _, SOME e) => cu inner e
108 | ENone _ => true
109 | ESome (_, e) => cu inner e
110 | EFfi _ => true
111 | EFfiApp (_, _, es) => List.all (cu inner) es
112 | EApp (e1, e2) => cu inner e1 andalso cu inner e2
113 | EAbs (_, _, _, e) => cu (inner + 1) e
114 | EUnop (_, e) => cu inner e
115 | EBinop (_, e1, e2) => cu inner e1 andalso cu inner e2
116 | ERecord xes => List.all (fn (_, e, _) => cu inner e) xes
117 | EField (e, _) => cu inner e
118 | ECase (e, pes, _) =>
119 cu inner e
120 andalso List.all (fn (p, e) => cu (inner + E.patBindsN p) e) pes
121 | EStrcat (e1, e2) => cu inner e1 andalso cu inner e2
122 | EError (e, _) => cu inner e
123 | EWrite e => cu inner e
124 | ESeq (e1, e2) => cu inner e1 andalso cu inner e2
125 | ELet (_, _, e1, e2) => cu inner e1 andalso cu (inner + 1) e2
126 | EClosure (_, es) => List.all (cu inner) es
127 | EQuery {query, body, initial, ...} =>
128 cu inner query
129 andalso cu (inner + 2) body
130 andalso cu inner initial
131 | EDml e => cu inner e
132 | ENextval e => cu inner e
133 | EUnurlify (e, _) => cu inner e
134 | EJavaScript (_, e, _) => cu inner e
135 | ESignalReturn e => cu inner e
136 | ESignalBind (e1, e2) => cu inner e1 andalso cu inner e2
137 | ESignalSource e => cu inner e
138 in
139 cu 0
140 end
141
99 fun strcat loc es = 142 fun strcat loc es =
100 case es of 143 case es of
101 [] => (EPrim (Prim.String ""), loc) 144 [] => (EPrim (Prim.String ""), loc)
102 | [x] => x 145 | [x] => x
103 | x :: es' => (EStrcat (x, strcat loc es'), loc) 146 | x :: es' => (EStrcat (x, strcat loc es'), loc)
104
105 exception Unsupported of string * EM.span
106 147
107 fun process file = 148 fun process file =
108 let 149 let
109 val nameds = foldl (fn ((DVal (_, n, t, e, _), _), nameds) => IM.insert (nameds, n, e) 150 val nameds = foldl (fn ((DVal (_, n, t, e, _), _), nameds) => IM.insert (nameds, n, e)
110 | ((DValRec vis, _), nameds) => 151 | ((DValRec vis, _), nameds) =>
121 (EFfiApp ("Basis", "htmlifyInt", [e]), loc)] 162 (EFfiApp ("Basis", "htmlifyInt", [e]), loc)]
122 | TRecord [] => str loc "null" 163 | TRecord [] => str loc "null"
123 164
124 | TFfi ("Basis", "string") => e 165 | TFfi ("Basis", "string") => e
125 | TFfi ("Basis", "int") => (EFfiApp ("Basis", "htmlifyInt", [e]), loc) 166 | TFfi ("Basis", "int") => (EFfiApp ("Basis", "htmlifyInt", [e]), loc)
167 | TFfi ("Basis", "float") => (EFfiApp ("Basis", "htmlifyFloat", [e]), loc)
126 168
127 | _ => (EM.errorAt loc "Don't know how to embed type in JavaScript"; 169 | _ => (EM.errorAt loc "Don't know how to embed type in JavaScript";
128 Print.prefaces "Can't embed" [("t", MonoPrint.p_typ MonoEnv.empty t)]; 170 Print.prefaces "Can't embed" [("t", MonoPrint.p_typ MonoEnv.empty t)];
129 str loc "ERROR") 171 str loc "ERROR")
130 172
149 case t of 191 case t of
150 TOption _ => true 192 TOption _ => true
151 | TRecord [] => true 193 | TRecord [] => true
152 | _ => false 194 | _ => false
153 195
154 fun unsupported s = raise Unsupported (s, loc) 196 fun unsupported s =
197 (EM.errorAt loc (s ^ " in code to be compiled to JavaScript[2]");
198 (str "ERROR", st))
155 199
156 val strcat = strcat loc 200 val strcat = strcat loc
157 201
158 fun jsPrim p = 202 fun jsPrim p =
159 case p of 203 case p of
445 in 489 in
446 (strcat [e, 490 (strcat [e,
447 str ("._" ^ x)], st) 491 str ("._" ^ x)], st)
448 end 492 end
449 493
450 | ECase (e, pes, _) => 494 | ECase (e', pes, {result, ...}) =>
451 let 495 if closedUpto inner e andalso List.all (fn (_, e) => closedUpto inner e) pes then
452 val plen = length pes 496 ((ELet ("js", result, e, quoteExp result (ERel 0, loc)), loc),
453 497 st)
454 val (cases, st) = ListUtil.foldliMap 498 else
455 (fn (i, (p, e), st) => 499 let
456 let 500 val plen = length pes
457 val (e, st) = jsE (inner + E.patBindsN p) (e, st) 501
458 val fail = 502 val (cases, st) = ListUtil.foldliMap
459 if i = plen - 1 then 503 (fn (i, (p, e), st) =>
460 str "pf()" 504 let
461 else 505 val (e, st) = jsE (inner + E.patBindsN p) (e, st)
462 str ("c" ^ Int.toString (i+1) ^ "()") 506 val fail =
463 val c = jsPat 0 inner p e fail 507 if i = plen - 1 then
464 in 508 str "pf()"
465 (strcat [str ("c" ^ Int.toString i ^ "=function(){return "), 509 else
466 c, 510 str ("c" ^ Int.toString (i+1) ^ "()")
467 str "},"], 511 val c = jsPat 0 inner p e fail
468 st) 512 in
469 end) 513 (strcat [str ("c" ^ Int.toString i ^ "=function(){return "),
470 st pes 514 c,
471 515 str "},"],
472 val (e, st) = jsE inner (e, st) 516 st)
473 in 517 end)
474 (strcat (str "(" 518 st pes
475 :: List.revAppend (cases, 519
476 [str "d0=", 520 val (e, st) = jsE inner (e', st)
477 e, 521 in
478 str ",c0())"])), st) 522 (strcat (str "("
479 end 523 :: List.revAppend (cases,
524 [str "d0=",
525 e,
526 str ",c0())"])), st)
527 end
480 528
481 | EStrcat (e1, e2) => 529 | EStrcat (e1, e2) =>
482 let 530 let
483 val (e1, st) = jsE inner (e1, st) 531 val (e1, st) = jsE inner (e1, st)
484 val (e2, st) = jsE inner (e2, st) 532 val (e2, st) = jsE inner (e2, st)
520 str ",", 568 str ",",
521 e2, 569 e2,
522 str ")"], st) 570 str ")"], st)
523 end 571 end
524 572
525 | EJavaScript (_, _, SOME e) => (e, st) 573 | EJavaScript (_, _, SOME _) => (e, st)
526 574
527 | EClosure _ => unsupported "EClosure" 575 | EClosure _ => unsupported "EClosure"
528 | EQuery _ => unsupported "Query" 576 | EQuery _ => unsupported "Query"
529 | EDml _ => unsupported "DML" 577 | EDml _ => unsupported "DML"
530 | ENextval _ => unsupported "Nextval" 578 | ENextval _ => unsupported "Nextval"
582 in 630 in
583 (EJavaScript (m, orig, SOME (strcat (#2 e) (locals @ [e]))), st) 631 (EJavaScript (m, orig, SOME (strcat (#2 e) (locals @ [e]))), st)
584 end 632 end
585 in 633 in
586 case e of 634 case e of
587 EJavaScript (m as Source t, orig, _) => 635 EJavaScript (m, orig as (EAbs (_, t, _, e), _), NONE) =>
588 (doCode m 0 env orig orig 636 doCode m 1 (t :: env) orig e
589 handle Unsupported (s, loc) => 637 | EJavaScript (m, orig, NONE) =>
590 let 638 doCode m 0 env orig orig
591 val e = ELet ("js", t, orig, quoteExp (#2 orig) t
592 (ERel 0, #2 orig))
593 in
594 (EJavaScript (m, orig, SOME (e, #2 orig)), st)
595 end)
596
597 | EJavaScript (m, orig as (EAbs (_, t, _, e), _), _) =>
598 (doCode m 1 (t :: env) orig e
599 handle Unsupported (s, loc) =>
600 (EM.errorAt loc (s ^ " in code to be compiled to JavaScript");
601 (EPrim (Prim.String "ERROR"), st)))
602
603 | EJavaScript (m, orig, _) =>
604 (doCode m 0 env orig orig
605 handle Unsupported (s, loc) =>
606 (EM.errorAt loc (s ^ " in code to be compiled to JavaScript");
607 (EPrim (Prim.String "ERROR"), st)))
608
609 | _ => (e, st) 639 | _ => (e, st)
610 end, 640 end,
611 decl = fn (_, e, st) => (e, st), 641 decl = fn (_, e, st) => (e, st),
612 bind = fn (env, U.Decl.RelE (_, t)) => t :: env 642 bind = fn (env, U.Decl.RelE (_, t)) => t :: env
613 | (env, _) => env} 643 | (env, _) => env}