summaryrefslogtreecommitdiff
path: root/src/name_js.sml
diff options
context:
space:
mode:
authorGravatar Adam Chlipala <adam@chlipala.net>2012-08-02 18:12:37 -0400
committerGravatar Adam Chlipala <adam@chlipala.net>2012-08-02 18:12:37 -0400
commita8ae5c1814db75525bf0ab199b0e5bd08c2c558a (patch)
tree212d4eb5fff81460457ee63a17c13dc26b79091b /src/name_js.sml
parentfdc6c1310be60fbeb597400618473861f78676de (diff)
New NameJs phase, still needing some debugging
Diffstat (limited to 'src/name_js.sml')
-rw-r--r--src/name_js.sml151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/name_js.sml b/src/name_js.sml
new file mode 100644
index 00000000..70ac000c
--- /dev/null
+++ b/src/name_js.sml
@@ -0,0 +1,151 @@
+(* Copyright (c) 2012, Adam Chlipala
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - The names of contributors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *)
+
+(* Phase that introduces names for fragments of JavaScript code, so that they
+ * may be moved to app.js and not repeated in each generated page *)
+
+structure NameJS :> NAME_JS = struct
+
+open Mono
+
+structure U = MonoUtil
+structure IS = IntBinarySet
+
+val freeVars = U.Exp.foldB {typ = #2,
+ exp = fn (free, e, vs) =>
+ case e of
+ ERel n =>
+ if n < free then
+ vs
+ else
+ IS.add (vs, n - free)
+ | _ => vs,
+ bind = fn (free, b) =>
+ case b of
+ U.Exp.RelE _ => free+1
+ | _ => free}
+ 0 IS.empty
+
+fun index (ls, v) =
+ case ls of
+ [] => raise Fail "NameJs.index"
+ | v' :: ls' => if v = v' then 0 else 1 + index (ls', v)
+
+fun squish vs = U.Exp.mapB {typ = fn x => x,
+ exp = fn free => fn e =>
+ case e of
+ ERel n =>
+ if n < free then
+ e
+ else
+ ERel (free + index (vs, n - free) + 1)
+ | _ => e,
+ bind = fn (free, b) =>
+ case b of
+ U.Exp.RelE _ => free+1
+ | _ => free}
+ 0
+
+fun rewrite file =
+ let
+ val (file, _) = ListUtil.foldlMapConcat (fn (d, nextName) =>
+ let
+ val (d, (nextName, newDs)) =
+ U.Decl.foldMapB {typ = fn x => x,
+ decl = fn (_, e, s) => (e, s),
+ exp = fn (env, e, st as (nextName, newDs)) =>
+ case e of
+ EJavaScript (mode, e') =>
+ (case mode of
+ Source _ => (e, st)
+ | _ =>
+ let
+ fun isTrulySimple (e, _) =
+ case e of
+ ERel _ => true
+ | ENamed _ => true
+ | ERecord [] => true
+ | _ => false
+
+ fun isAlreadySimple e =
+ case #1 e of
+ EApp (e, arg) => isTrulySimple arg andalso isAlreadySimple e
+ | _ => isTrulySimple e
+ in
+ if isAlreadySimple e' then
+ (e, st)
+ else
+ let
+ val loc = #2 e'
+
+ val vs = freeVars e'
+ val vs = IS.listItems vs
+
+ val x = "script" ^ Int.toString nextName
+
+ val un = (TRecord [], loc)
+ val s = (TFfi ("Basis", "string"), loc)
+ val base = (TFun (un, s), loc)
+ val t = foldl (fn (n, t) => (TFun (#2 (List.nth (env, n)), t), loc)) base vs
+ val e' = squish vs e'
+ val e' = (EAbs ("_", un, s, e'), loc)
+ val (e', _) = foldl (fn (n, (e', t)) =>
+ let
+ val (x, this) = List.nth (env, n)
+ in
+ ((EAbs (x, this, t, e'), loc),
+ (TFun (this, t), loc))
+ end) (e', base) vs
+ val d = (x, nextName, t, e', "<script>")
+
+ val e = (ENamed nextName, loc)
+ val e = foldr (fn (n, e) => (EApp (e, (ERel n, loc)), loc)) e vs
+ val e = (EApp (e, (ERecord [], loc)), loc)
+ val e = EJavaScript (Script, e)
+ in
+ (e, (nextName+1, d :: newDs))
+ end
+ end)
+ | _ => (e, st),
+ bind = fn (env, b) =>
+ case b of
+ U.Decl.RelE x => x :: env
+ | _ => env}
+ [] (nextName, []) d
+ in
+ (case newDs of
+ [] => [d]
+ | _ => case #1 d of
+ DValRec vis => [(DValRec (vis @ newDs), #2 d)]
+ | _ => List.revAppend (map (fn vi => (DVal vi, #2 d)) newDs, [d]),
+ nextName)
+ end) (U.File.maxName file + 1) file
+ in
+ file
+ end
+
+end