Mercurial > urweb
comparison src/name_js.sml @ 1800:38297294cf98
New NameJs phase, still needing some debugging
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Thu, 02 Aug 2012 18:12:37 -0400 |
parents | |
children | c1e3805e604e |
comparison
equal
deleted
inserted
replaced
1799:3d922a28370b | 1800:38297294cf98 |
---|---|
1 (* Copyright (c) 2012, Adam Chlipala | |
2 * All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are met: | |
6 * | |
7 * - Redistributions of source code must retain the above copyright notice, | |
8 * this list of conditions and the following disclaimer. | |
9 * - Redistributions in binary form must reproduce the above copyright notice, | |
10 * this list of conditions and the following disclaimer in the documentation | |
11 * and/or other materials provided with the distribution. | |
12 * - The names of contributors may not be used to endorse or promote products | |
13 * derived from this software without specific prior written permission. | |
14 * | |
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
25 * POSSIBILITY OF SUCH DAMAGE. | |
26 *) | |
27 | |
28 (* Phase that introduces names for fragments of JavaScript code, so that they | |
29 * may be moved to app.js and not repeated in each generated page *) | |
30 | |
31 structure NameJS :> NAME_JS = struct | |
32 | |
33 open Mono | |
34 | |
35 structure U = MonoUtil | |
36 structure IS = IntBinarySet | |
37 | |
38 val freeVars = U.Exp.foldB {typ = #2, | |
39 exp = fn (free, e, vs) => | |
40 case e of | |
41 ERel n => | |
42 if n < free then | |
43 vs | |
44 else | |
45 IS.add (vs, n - free) | |
46 | _ => vs, | |
47 bind = fn (free, b) => | |
48 case b of | |
49 U.Exp.RelE _ => free+1 | |
50 | _ => free} | |
51 0 IS.empty | |
52 | |
53 fun index (ls, v) = | |
54 case ls of | |
55 [] => raise Fail "NameJs.index" | |
56 | v' :: ls' => if v = v' then 0 else 1 + index (ls', v) | |
57 | |
58 fun squish vs = U.Exp.mapB {typ = fn x => x, | |
59 exp = fn free => fn e => | |
60 case e of | |
61 ERel n => | |
62 if n < free then | |
63 e | |
64 else | |
65 ERel (free + index (vs, n - free) + 1) | |
66 | _ => e, | |
67 bind = fn (free, b) => | |
68 case b of | |
69 U.Exp.RelE _ => free+1 | |
70 | _ => free} | |
71 0 | |
72 | |
73 fun rewrite file = | |
74 let | |
75 val (file, _) = ListUtil.foldlMapConcat (fn (d, nextName) => | |
76 let | |
77 val (d, (nextName, newDs)) = | |
78 U.Decl.foldMapB {typ = fn x => x, | |
79 decl = fn (_, e, s) => (e, s), | |
80 exp = fn (env, e, st as (nextName, newDs)) => | |
81 case e of | |
82 EJavaScript (mode, e') => | |
83 (case mode of | |
84 Source _ => (e, st) | |
85 | _ => | |
86 let | |
87 fun isTrulySimple (e, _) = | |
88 case e of | |
89 ERel _ => true | |
90 | ENamed _ => true | |
91 | ERecord [] => true | |
92 | _ => false | |
93 | |
94 fun isAlreadySimple e = | |
95 case #1 e of | |
96 EApp (e, arg) => isTrulySimple arg andalso isAlreadySimple e | |
97 | _ => isTrulySimple e | |
98 in | |
99 if isAlreadySimple e' then | |
100 (e, st) | |
101 else | |
102 let | |
103 val loc = #2 e' | |
104 | |
105 val vs = freeVars e' | |
106 val vs = IS.listItems vs | |
107 | |
108 val x = "script" ^ Int.toString nextName | |
109 | |
110 val un = (TRecord [], loc) | |
111 val s = (TFfi ("Basis", "string"), loc) | |
112 val base = (TFun (un, s), loc) | |
113 val t = foldl (fn (n, t) => (TFun (#2 (List.nth (env, n)), t), loc)) base vs | |
114 val e' = squish vs e' | |
115 val e' = (EAbs ("_", un, s, e'), loc) | |
116 val (e', _) = foldl (fn (n, (e', t)) => | |
117 let | |
118 val (x, this) = List.nth (env, n) | |
119 in | |
120 ((EAbs (x, this, t, e'), loc), | |
121 (TFun (this, t), loc)) | |
122 end) (e', base) vs | |
123 val d = (x, nextName, t, e', "<script>") | |
124 | |
125 val e = (ENamed nextName, loc) | |
126 val e = foldr (fn (n, e) => (EApp (e, (ERel n, loc)), loc)) e vs | |
127 val e = (EApp (e, (ERecord [], loc)), loc) | |
128 val e = EJavaScript (Script, e) | |
129 in | |
130 (e, (nextName+1, d :: newDs)) | |
131 end | |
132 end) | |
133 | _ => (e, st), | |
134 bind = fn (env, b) => | |
135 case b of | |
136 U.Decl.RelE x => x :: env | |
137 | _ => env} | |
138 [] (nextName, []) d | |
139 in | |
140 (case newDs of | |
141 [] => [d] | |
142 | _ => case #1 d of | |
143 DValRec vis => [(DValRec (vis @ newDs), #2 d)] | |
144 | _ => List.revAppend (map (fn vi => (DVal vi, #2 d)) newDs, [d]), | |
145 nextName) | |
146 end) (U.File.maxName file + 1) file | |
147 in | |
148 file | |
149 end | |
150 | |
151 end |