commit 69640b8ad79b8112d5ace2409934d3e8eba71c43
parent f829c1790b61532efbbdc62fc74ebf91b642f3b1
Author: tomas <tomas@logand.com>
Date:   Tue,  6 Oct 2009 21:07:33 +0200
generic Any used
Diffstat:
| M | wl.java |  |  | 575 | ++++++++++++++++++++++++++----------------------------------------------------- | 
1 file changed, 189 insertions(+), 386 deletions(-)
diff --git a/wl.java b/wl.java
@@ -5,17 +5,36 @@ import java.util.HashMap;
 
 class wl {
 
+    void err(Object X, String M) {
+        if(X instanceof Any) throw new RuntimeException(M + ": " + str((Any) X));
+        throw new RuntimeException(M + ": " + X);
+    }
+    void err(String M) {throw new RuntimeException(M);}
+
+    static interface Fn {
+        public Any fn(Any E);
+    }
+
     static class Any {
         public String nm;
-        public Object car, cdr;
-        public Any(String n, Object a, Object d) {nm = n; car = a; cdr = d;}
-        public isSym() {return null != nm;}
-        public isCons() {return null == nm;}
+        public Any car, cdr;
+        public Object cxr;
+        public Any(String n, Any a, Any d, Object x) {
+            nm = n; car = a; cdr = d; cxr = x;
+        }
+        public boolean isSym() {return null != nm;}
+        public boolean isCons() {return null == nm && null != car && null != cdr;}
+        public boolean isStr() {return null == nm && cxr instanceof String;}
+        public boolean isInt() {return null == nm && cxr instanceof Integer;}
+        public boolean isFn() {return cxr instanceof Fn;}
     }
-    static Any cons(Any a, Any d) {return new Any(null, a, d);}
+    static Any cons(Any a, Any d) {return new Any(null, a, d, null);}
+    static Any mkInt(String x) {return new Any(null, null, null, Integer.parseInt(x));}
+    static Any mkFix(String x) {return new Any(null, null, null, Float.parseFloat(x));}
+    static Any mkStr(String x) {return new Any(null, null, null, x);}
 
-    final static Any NIL = new Any("NIL", null, null);
-    final static Any T = new Any("T", NIL, null);
+    final static Any NIL = new Any("NIL", null, null, null);
+    final static Any T = new Any("T", NIL, null, null);
 
     static {
         NIL.car = NIL;
@@ -23,31 +42,10 @@ class wl {
         T.cdr = T;
     }
 
-    // static class Cons {
-    //     public Object car, cdr;
-    //     public Cons(Object a, Object d) {car = a; cdr = d;}
-    // }
-    // static Cons cons(Object a, Object d) {return new Cons(a, d);}
-
-    // static class Sym {
-    //     public String nm;
-    //     public Object car, cdr;
-    //     public Sym(String n, Object a, Object d) {nm = n; car = a; cdr = d;}
-    // }
-
-    // final static Sym NIL = new Sym("NIL", null, null);
-    // final static Sym T = new Sym("T", NIL, null);
-
-    // static {
-    //     NIL.car = NIL;
-    //     NIL.cdr = NIL;
-    //     T.cdr = T;
-    // }
-
     // reader
-    final static Object Qte = new Object();
-    final static Object Lp = new Object();
-    final static Object Rp = new Object();
+    final static Any Qte = new Any(null, null, null, null);
+    final static Any Lp = new Any(null, null, null, null);
+    final static Any Rp = new Any(null, null, null, null);
 
     String L;
     int N, I, D;
@@ -69,7 +67,7 @@ class wl {
             skip();
         }
     }
-    String text() {
+    Any text() {
         StringBuffer L = new StringBuffer();
         while('"' != peek()) {
             Character C = xchar();
@@ -83,14 +81,13 @@ class wl {
             }
             L.append(C);
         }
-        if('"' != xchar()) throw new RuntimeException("Unbalanced double quote");
-        if(0 < L.length()) return L.toString(); //.replace(/\r\n/g, "\n");
-        return "";
+        if('"' != xchar()) err("Unbalanced double quote");
+        if(0 < L.length()) return mkStr(L.toString()); //.replace(/\r\n/g, "\n");
+        return mkStr("");
     }
-    Object symbol() {
+    Any symbol() {
         Character C = xchar();
-        if(charIn(C, "()# \t\n"))
-            throw new RuntimeException("Symbol expected, got " + C);
+        if(charIn(C, "()# \t\n")) err(C, "Symbol expected");
         boolean N = charIn(C, "+-0123456789.");
         boolean F = ('.' == C);
         StringBuffer L = new StringBuffer();
@@ -106,9 +103,9 @@ class wl {
         }
         String M = L.toString();
         if((1 == M.length()) && charIn(M.charAt(0), "+-.")) N = false;
-        return N ? (F ? Float.parseFloat(M) : Integer.parseInt(M, 10)) : intern(M);
+        return N ? (F ? mkFix(M) : mkInt(M)) : intern(M);
     }
-    Object token() {
+    Any token() {
         skip();
         Character X = peek();
         if(null == X) return null;
@@ -124,127 +121,212 @@ class wl {
     }
 
     // parser
-    Object parseBuild(Stack Os) {
-        Object Z = null;
-        Object Dot = null;
+    Any parseBuild(Stack<Any> Os) {
+        Any Z = NIL;
+        Any Dot = null;
         while(0 < Os.size()) {
-            Object X = Os.pop();
+            Any X = Os.pop();
             if(Lp == X) return Dot != null ? cons(Dot, cons(Z, NIL)) : Z;
             Dot = null;
-            if((X instanceof Sym) && (".".equals(((Sym) X).nm))) {
-                if((Z instanceof Cons) && (null == ((Cons) Z).cdr)) {
-                    Z = ((Cons) Z).car;
+            if(X.isSym() && (".".equals(X.nm))) {
+                if(Z.isCons() && NIL == Z.cdr) {
+                    Z = Z.car;
                     Dot = X;
-                } else throw new RuntimeException("Bad dotted pair");
+                } else err("Bad dotted pair");
             } else if(X == Qte)
-                Z = cons(cons(this.Sd.get("quote"), ((Cons) Z).car), ((Cons) Z).cdr);
-            else Z = cons(X, Z == null ? NIL : Z);
+                Z = cons(cons(this.Sd.get("quote"), Z.car), Z.cdr);
+            else Z = cons(X, Z);
         }
-        throw new RuntimeException("Missing mark");
+        err("Missing mark");
+        return NIL; // make compiler happy:-{
     }
-    Object parse(String L) {
+    public Any parse(String L) {
         init(L);
-        Stack Os = new Stack();
+        Stack<Any> Os = new Stack<Any>();
         Os.push(Lp);
         // TODO circular list .
         // TODO interpret while reading ~ for each top-level sexp
         // TODO no wasteful consing
         while(null != peek()) {
-            Object X = token();
+            Any X = token();
             if(null != X) {
                 if(Rp == X) Os.push(parseBuild(Os));
                 else Os.push(X);
             }
         }
-        Object Z = parseBuild(Os);
-        if(0 < Os.size())
-            throw new RuntimeException("Incomplete input, left with " + Os);
+        Any Z = parseBuild(Os);
+        if(0 < Os.size()) err(Os, "Incomplete input");
         return Z;
     }
 
     // printer
-    String str(Object L) {
+    public String str(Any L) {
         StringBuilder A = new StringBuilder();
-        if(L instanceof Sym) A.append(L.nm);
-        else if(L instanceof Cons) {
+        if(L.isSym()) A.append(L.nm);
+        else if(L.isInt()) A.append(L.cxr.toString());
+        else if(L.isCons()) {
             if(this.Sd.get("quote") == L.car) {
                 A.append('\'');
                 A.append(str(L.cdr));
             } else {
                 A.append('(');
-                while(L instanceof Cons) {
+                while(L.isCons()) {
                     A.append(str(L.car));
                     L = L.cdr;
-                    if(NIL !== L) A.append(' ');
+                    if(NIL != L) A.append(' ');
                 }
-                if(NIL !== L) {
+                if(NIL != L) {
                     A.append(". ");
                     A.append(str(L));
                 }
                 A.append(')');
             }
-        } else if(L instanceof String) {
-            var Y = L.split("");
-            for(var I = 0; I < Y.length; I++) {
-                if(Y[I] == "\\") Y[I] = "\\\\";
-                else if(Y[I] == '"') Y[I] = '\\"';
-            }
-            var S = Y.join("");
-            //var S = L.replace(/\"/g, "\\\"").replace(/\\/g, "\\\\");
+        } else if(L.isStr()) {
             A.append('"');
-            A.append(S);
+            String S = (String) L.cxr;
+            for(int I = 0; I < S.length(); I++) {
+                Character C = S.charAt(I);
+                if('\\' == C) A.append("\\\\");
+                else if('"' == C) A.append("\\\"");
+                else A.append(C);
+            }
             A.append('"');
-        } else A.append(L);
+        } else err(L, "Don't know how to print");
         return A.toString();
     }
 
 
     // evaluator
-    HashMap Sd = new HashMap();
+    HashMap<String, Any> Sd = new HashMap<String, Any>();
 
-    Sym intern(String Nm) {
-        if(!this.Sd.containsKey(Nm)) this.Sd.put(Nm, new Sym(Nm, NIL, NIL));
-        return (Sym) this.Sd.get(Nm);
+    Any intern(String Nm) {
+        if(!this.Sd.containsKey(Nm)) this.Sd.put(Nm, new Any(Nm, NIL, NIL, null));
+        return this.Sd.get(Nm);
     }
-    void def(String Nm, Object Val) {
-        if(this.Sd.containsKey(Nm)) ((Sym) this.Sd.get(Nm)).cdr = Val;
-        else this.Sd.put(Nm, new Sym(Nm, Val, NIL));
+    // void def(String Nm, Fn F) {
+    //     if(this.Sd.containsKey(Nm)) this.Sd.get(Nm).cxr = F;
+    //     else this.Sd.put(Nm, new Sym(Nm, null, null, F));
+    // }
+
+    Any run(Any E) {
+        System.out.println("run: " + str(E));
+        Any Z = NIL;
+        while(NIL != E) {
+            Z = eval(E.car);
+            E = E.cdr;
+        }
+        return Z;
+    }
+    Any eval(Any E) {
+        System.out.println("eval: " + str(E));
+        Any Z = NIL;
+        if(E.isInt()) Z = E;
+        else if(E.isSym()) Z = E.cdr;
+        else if(E.isCons()) {
+            Any X = E.car;
+            if(X.isInt()) Z = E;
+            else if(X.isSym()) {
+                if(X.isFn()) Z = ((Fn) X.cxr).fn(E);
+                else err(E, "TODO ap"); //Z = ap(E);
+            } else err(E, "Unexpected function type");
+        } else Z = E; // string
+        //alert("ev: " + str(E) + " => " + Z);
+        return Z;
+    }
+
+    void fn(String Nm, Fn F) {this.Sd.put(Nm, new Any(Nm, null, null, F));}
+
+    public wl() {
+        Sd.put("NIL", NIL);
+        Sd.put("T", T);
+        
+        fn("run", new Fn() {public Any fn(Any E) {return run(E);}});
+        fn("eval", new Fn() {public Any fn(Any E) {return eval(E);}});
+        fn("quote", new Fn() {public Any fn(Any E) {return E.cdr;}});
+        fn("car", new Fn() {public Any fn(Any E) {return eval(E.cdr.car).car;}});
+        fn("cdr", new Fn() {public Any fn(Any E) {return eval(E.cdr.car).cdr;}});
+        fn("-", new Fn() {public Any fn(Any E) {
+            Any X = E.cdr;
+            Any Z = eval(X.car);
+            if(NIL == Z) return NIL;
+            if(NIL == X.cdr) Z.cxr = -((Integer) Z.cxr);
+            else
+                while(NIL != X.cdr) {
+                    X = X.cdr;
+                    Any Y = eval(X.car);
+                    if(NIL == Y) return NIL;
+                    Z.cxr = (Integer) Z.cxr - (Integer) Y.cxr;
+                }
+            return Z;
+        }});
+        fn("*", new Fn() {public Any fn(Any E) {
+            Any X = E.cdr;
+            Any Z = eval(X.car);
+            if(NIL == Z) return NIL;
+            while(NIL != X.cdr) {
+                X = X.cdr;
+                Any Y = eval(X.car);
+                if(NIL == Y) return NIL;
+                Z.cxr = (Integer) Z.cxr * (Integer) Y.cxr;
+            }
+            return Z;
+        }});
+        fn("/", new Fn() {public Any fn(Any E) {
+            Any X = E.cdr;
+            Any Z = eval(X.car);
+            if(NIL == Z) return NIL;
+            while(NIL != X.cdr) {
+                X = X.cdr;
+                Any Y = eval(X.car);
+                if(NIL == Y) return NIL;
+                Z.cxr = (Integer) Z.cxr / (Integer) Y.cxr;
+            }
+            return Z;
+        }});
+        fn("loop", new Fn() {public Any fn(Any E) {
+            // TODO @
+            while(true) {
+                for(Any X = E.cdr; NIL != X.cdr; X = X.cdr) {
+                    Any Y = X.car;
+                    if(Y.isCons() && NIL == Y) {
+                        Y = Y.cdr;
+                        if(NIL == eval(Y.car)) return run(Y.cdr);
+                    } else if(Y.isCons() && T == Y) {
+                        Y = Y.cdr;
+                        if(NIL != eval(Y.car)) return run(Y.cdr);
+                    } else eval(Y);
+                }
+            }
+        }});
+        fn("==", new Fn() {public Any fn(Any E) {
+            Any X = E.cdr;
+            return eval(X.car) == eval(X.cdr.car) ? T : NIL;
+        }});
+
+        fn("in", new Fn() {public Any fn(Any E) {
+            Any X = E.cdr;
+            Any N = eval(E.car);
+            String F;
+            if(N.isStr()) F = (String) N.cxr;
+            else if(N.isSym()) F = N.nm;
+            else err(E, "File name expected");
+            //FileInputStream S = new FileInputStream(N);
+            //InputStreamReader R = new InputStreamReader(S, "UTF-8");
+            return NIL;
+        }});
+        //FileOutputStream fos = new FileOutputStream("test.txt");
+        //OutputStreamWriter out = new OutputStreamWriter(fos, "UTF-8"); 
     }
 
 
 
     public static void main(String args[]) {
         wl X = new wl();
-        //wl.init("(+ 1 2 3)");
+        System.out.println(X.str(X.parse("(- 1 2 3)")));
+        System.out.println(X.str(X.run(X.parse("(- 1 2 3)(- 3 5)(/ "))));
     }
 }
 
-//     // TODO fix E ~ whole sexp fn
-
-//     function run(E) {
-//         var Z;
-//         while(NIL !== E) {
-//             Z = ev(E.car);
-//             E = E.cdr;
-//         }
-//         return Z;
-//     }
-//     function ev(E) { // eval
-//         var Z;
-//         if(typeof E == "number") Z = E;
-//         else if(isSym(E)) Z = E.cdr;
-//         else if(isCons(E)) {
-//             var X = E.car;
-//             if(typeof X == "number") Z = E;
-//             else if(isSym(X)) {
-//                 if(typeof X.cdr == "function") Z = X.cdr(E);
-//                 else throw "TODO ap"; //Z = ap(E);
-//             } else throw "Unexpected function type";
-//         } else Z = E; // string
-//         //alert("ev: " + str(E) + " => " + Z);
-//         return Z;
-//     }
-
 //     // TODO ap
 //     function ap(E) { // apply
 //         var Z;
@@ -261,10 +343,7 @@ class wl {
 //         } else throw "Function expected";
 //     }
 
-//     //def("run", run);
-//     //def("eval", ev);
 //     //def("apply", ap);
-//     def("quote", function(E) {return E.cdr;});
 
 //     def("val", function(E) {
 //             var Z;
@@ -280,289 +359,13 @@ class wl {
 //     // TODO def !!!!!!!!!!!!!
 
 //     // OK
-//     def("car", function(E) {return ev(E.cdr.car).car;});
-//     def("cdr", function(E) {return ev(E.cdr.car).cdr;});
-//     def("-", function(E) {
-//             var X = E.cdr;
-//             var Z = ev(X.car);
-//             if(NIL === Z) return NIL;
-//             if(NIL === X.cdr) Z = -Z;
-//             else
-//                 while(NIL !== X.cdr) {
-//                     X = X.cdr;
-//                     var Y = ev(X.car);
-//                     if(NIL === Y) return NIL;
-//                     Z -= Y;
-//                 }
-//             return Z;
-//         });
-//     def("*", function(E) {
-//             var X = E.cdr;
-//             var Z = ev(X.car);
-//             if(NIL === Z) return NIL;
-//             while(NIL !== X.cdr) {
-//                 X = X.cdr;
-//                 var Y = ev(X.car);
-//                 if(NIL === Y) return NIL;
-//                 Z *= Y;
-//             }
-//             return Z;
-//         });
-//     def("/", function(E) {
-//             var X = E.cdr;
-//             var Z = ev(X.car);
-//             if(NIL === Z) return NIL;
-//             while(NIL !== X.cdr) {
-//                 X = X.cdr;
-//                 var Y = ev(X.car);
-//                 if(NIL === Y) return NIL;
-//                 Z /= Y;
-//             }
-//             return Z;
-//         });
 
 // //     Sd["%"] = function(E) {var X = Os.pop(); Os.push(Os.pop() % X);};
 // //     Sd["eq"] = function() {var Y = Os.pop(); var X = Os.pop(); Os.push(X == Y);};
 // //     Sd["lt"] = function() {var Y = Os.pop(); var X = Os.pop(); Os.push(X < Y);};
 
-//     wl.prototype.parse = parse;
-//     wl.prototype.str = str;
-//     wl.prototype.run = run;
-//     return this;
-// }
-
-
-
-
-
-
-
-
-// //     Sd["if"] = function() {
-// //         var N = Os.pop();
-// //         var P = Os.pop();
-// //         var C = Os.pop();
-// //         Es.push([false, C === true ? P : N]);
-// //     };
-
-// //     // Sd[".call"] = function() {
-// //     //     var N = Os.pop();
-// //     //     var K = Os.pop();
-// //     //     var D = Os.pop();
-// //     //     var X = [];
-// //     //     for(var I = 0; I < N; I++) X.unshift(Os.pop());
-// //     //     Os.push(D[K].apply(D, X));
-// //     // };
-// //     Sd[".date"] = function(E) {return new Date();}; // TODO split new and Date
-// //     // Sd[".callback"] = function() { // TODO event arg?
-// //     //     var X = Os.pop();
-// //     //     Os.push(function() {
-// //     //                 Ps.run(X, true);
-// //     //                 while(0 < Es.length)
-// //     //                     Ps.step();
-// //     //             });
-// //     // };
-
-
-// //     Sd["list2array"] = function list2array(E) {
-// //         var Z = [];
-// //         while(!isNil(E)) {
-// //             Z.push(E.car);
-// //             E = E.cdr;
-// //         }
-// //         return Z;
-// //     };
-// //     // Sd["array2list"] = function array2list(A) {
-// //     //     var Z = NIL;
-// //     //     for(var I = A.length - 1; 0 <= I; I--)
-// //     //         Z = cons(A[I], Z);
-// //     //     return Z;
-// //     // };
-// //     // Sd["object2list"] = function object2list(O) {
-// //     //     var Z = NIL;
-// //     //     for(var I in O)
-// //     //         Z = cons(cons(I, O[I]), Z);
-// //     //     return Z;
-// //     // };
-
-// //     function parse() {
-// //         var Z;
-// //         var A = arguments;
-// //         if(A.length)
-// //             for(var I = 0; I < A.length; I++)
-// //                 Z = Rd.parse(A[I]);
-// //         else Z = Rd.parse(A);
-// //         return Z;
-// //     }
-// //     wl.prototype.parse = parse;
-// //     return this;
-// // }
-
-// // /// lisp
-
-// // // function format(N, S) {
-// // //     var X = "" + N;
-// // //     var L = X.length;
-// // //     return X.slice(0, L - S) + "." + X.slice(L - S, L);
-// // // }
-
-// // // function real(N, S) {
-// // //     return N / Math.pow(10, S);
-// // // }
-
-// // var Syms = {};
-
-// // function mkSym(Nm, Val, Prop) {
-// //     var X = new Sym(Nm, Val, Prop);
-// //     Syms[Nm] = X;
-// //     return X;
-// // }
-
-// // function xget(Sym) {
-// //     return isSym(Sym) ? Sym._val : Sym;
-// // }
-
-// // function xset(Sym, Val) {
-// //     if(!isSym(Sym)) throw "Sym expected";
-// //     Sym._val = Val;
-// //     return Sym._val;
-// // }
-
-// // //var NIL = mkSym("NIL");
-// // var T = mkSym("T");
-
-// // //xset(NIL, NIL);
-// // xset(T, T);
-// // // TODO set props for NIL and T
-
-// // function intern(Sym) {
-// //     //if(!(Sym in Syms)) Syms[Sym] = mkSym(Sym, NIL, NIL);
-// //     return Syms[Sym] || (Syms[Sym] = mkSym(Sym, NIL, NIL));
-// // }
-
-
-// // function isT(X) {
-// //     return X === T;
-// // }
-
-
-
-
-
-
-
-
 // // function eq(X, Y) {
 // //     if(X === Y) return T;
 // //     //if(X == Y) return T;
 // //     return NIL;
 // // }
-
-// // function xdelete(A, L) {
-// //     var X = NIL;
-// //     while(!isNil(L)) {
-// //         if(isNil(eq(A, L.car))) X = cons(L.car, X);
-// //         L = L.cdr;
-// //     }
-// //     return reverse(X);
-// // }
-
-// // function lsApply(Fn, Args) {
-// // }
-
-// // function jsFn(Fn) {
-// //     var F = function() {
-// //         return lsApply(Fn, list2array(arguments));
-// //     };
-// //     return F;
-// // }
-
-// // function jsApply() {
-// //     var Fn = arguments.shift();
-// //     var Args = arguments.shift();
-// //     var Rest = arguments;
-// //     return Fn.apply(list2array(Args).unshift.apply(list2array(Rest)));
-// // }
-
-// // var Xeval = {};
-
-// // function xdef(Nm, Fn) {
-// //     if(!(Nm in Syms)) intern(Nm);
-// //     Xeval[Nm] = Fn;
-// // }
-
-// // xdef("quote", function(E) {
-// //         return cdr(E); // or cdr?
-// //     });
-// // xdef("if", function(E) {
-// //         if(!isNil(xeval(cadr(E)))) return xeval(caddr(E));
-// //         else return xeval(cadddr(E));
-// //     });
-// // xdef("prog", function(E) {
-// //         var L = cdr(E);
-// //         var X = NIL;
-// //         while(!isNil(L)) {
-// //             X = xeval(L.car);
-// //             L = L.cdr;
-// //         }
-// //         return X;
-// //     });
-
-// // function xeval(E) {
-// //     if(isSym(E)) return xget(E);
-// //     else if(!isCons(E)) return E;
-// //     else if(car(E)._nm in Xeval) return Xeval[car(E)._nm](E);
-// //     else return xapply(xeval(car(E)), map(xeval, cdr(E)));
-// // }
-
-// // function initLisp() {
-// //     //xalert(xeval(NIL), xeval(T), xeval(12), xeval(12.3), xeval({x: "hi"}), xeval([1, 2]));
-// //     //xalert(xeval(cons(intern("quote"), cons("whoa", NIL))));
-// //     //xalert(xeval(cons(intern("quote"), cons("whoa", cons("b", NIL)))));
-// //     //xalert(intern("if"));
-// //     //xalert(object2list(Syms));
-// //     //xalert(object2list(Xeval));
-// //     //xalert(xeval(cons(intern("if"), cons(T, cons("yes", cons("no", NIL))))));
-// //     //xalert(xeval(cons(intern("if"), cons(NIL, cons("yes", cons("no", NIL))))));
-// //     //xalert(xeval(cons(intern("quote"), intern("whoa"))));
-// // }
-
-// // // parser
-
-// // function isArray(A) {
-// //     return A && A.constructor == Array;
-// // }
-
-// // function flatten(A) {
-// //     var X = [];
-// //     function rec(B) {
-// //         var N = B.length;
-// //         var I;
-// //         for(I = 0; I < N; I++) {
-// //             if(isArray(B[I])) rec(B[I]);
-// //             else X.push(B[I]);
-// //         }
-// //     }
-// //     rec(A);
-// //     return X;
-// // }
-
-// // function lisp2string(Any) {
-// //     return flatten(unparse(Any)).join("");
-// // }
-
-// // function xalert() {
-// //     var X = [];
-// //     var N = arguments.length;
-// //     var I;
-// //     for(I = 0; I < N; I++) {
-// //         X.push(flatten(unparse(arguments[I])).join(""));
-// //     }
-// //     alert(X.join(" "));
-// // }
-
-// // function xmsg(A) {
-// //     var B = parse(A);
-// //     var X = flatten(unparse(B)).join("");
-// //     mk(w("test"), "pre", {}, {}, "'" + A + "' => " + X);
-// // }