java/ch/wlkl/wsm/Test.java

package ch.wlkl.wsm;

import java.util.ArrayList;

import java.util.Arrays;
import java.util.function.Function;
import static ch.wlkl.env.Env.*;
import ch.wlkl.env.IOCompare;
import ch.wlkl.wsm.Syntax.SynSeq;
import java.util.Map;


public class Test extends IOCompare {

    /**
     * @param args
     */
    ExFactory y = new ExFactory();
    AbstractCompiler compiler = new Compiler(y);
    Frame bf = new Frame();

    final ArrayList<String> cName = new ArrayList();
    final ArrayList<Ex> cEx = new ArrayList();

    public void cAdd(String n, Ex e) {
        cName.add(n);
        cEx.add(e);
    }
    
    public void cClear() {
        cName.clear();
        cEx.clear();
    }

    public void formatSimple() {
        begin("formatSimple"
            , "syntaxFactory"
            , "syntax = ruleDef+"
            , "ruleDef = rule \"=\" or"
            , "or = seq (\"|\" seq)*"
            , "seq = loop+"
            , "loop = (lit | rule | lex | bracket) (\"?\" | \"*\" | \"+\")?"
            , "bracket = \"(\" (bracObj | or) \")\""
            , "bracObj = or"
            , "rule = <<<name>>>"
            , "lit = <<<lit>>>"
            , "lex = \"<<<\" <<<name>>> \">>>\""
            , "endFactory"
            );
        SyntaxFactory f = new SyntaxFactory();
        f.syntaxSyntax();
        Formatter out = Formatter.make();
        FormatFactory s = new FormatFactory();
        f.syntaxFormatSimple(s);
        s.finish();
        out.formatOk(s.atFor(f), f);
        out.toOut();
        out.reset();
        end();
    }

    public void formatMake() {
        begin("formatMake", "SyntaxFactory begin", "syntax = ruleDef+", "ruleDef = rule \"=\" or", "or = seq (\"|\" seq)*", "seq = loop+", "loop = (lit | rule | lex | bracket) (\"?\" | \"*\" | \"+\")?", "bracket = \"(\" (bracObj | or) \")\"", "bracObj = or", "rule = <<<name>>>", "lit = <<<lit>>>", "lex = \"<<<\" <<<name>>> \">>>\"", "SyntaxFactory end"
        );
        SyntaxFactory f = new SyntaxFactory();
        f.syntaxSyntax();
        FormatFactory s = new FormatFactory();
        f.makeFormat(s);
        Formatter out = Formatter.make();
        ((FormatFactory.Fmt) s.k2f.get(SyntaxFactory.class)).mergeSyn("SyntaxFactory begin , $ , SyntaxFactory end :,n$,n%");
        ((FormatFactory.Fmt) s.k2f.get(SynSeq.class)).mergeSyn(", | |1 | $ :,|| |$");
        ((FormatFactory.Fmt) s.k2f.get("ruleDef")).mergeLex(",$, % $");
        out.formatOk(f.rule("syntax").format, f);
        out.toOut();
        end();

        if (false) {
            all2s.restart();
        for (Map.Entry<String, Syntax.SynRule> e : f.rules.entrySet()) {
            out(e.getKey(), " ==> ", e.getValue());
        }
        f.syntaxFormatSimple(s);
        s.finish();
        out.formatOk(s.atFor(f), f);
        out.toOut();
        out.reset();
        end();
        }
    }
        
    public void testFormat(String nm, String... cmp) {
        begin(nm, cmp);
        Formatter o = Formatter.make();
        FormatFactory f = new FormatFactory();
        cEx.get(0).formatRulesDefault(f);
        for (int cx=0; cx < cName.size(); cx++) {
            o.reset();
            o.formatOk(f.atFor(cEx.get(cx)), cEx.get(cx));
            for (String li : (cName.get(cx) + /* " ==> " + a2r(f.atFor(cEx.get(cx)).code()) +  */ " ==> " + o.text()).split("\n")) {
                out(li);
            }
        }
        end();
    }

    public String sayFormat(String n) {
        out("--- " + n + " sayFormat ----------");
        for (int cx = 0; cx < cName.size(); cx++) {
            out(cName.get(cx) + " ??? " + cEx.get(cx));
            for (String li : (cName.get(cx) + " ==> " + cEx.get(cx).format()).split("\n")) {
                out(li);
            }
        }
        return "";
    }

    public String cFormat() {
        cClear();
        String d50 = ".........";
        d50 += '1' + d50 + '2' + d50 + '3' + d50 + '4' + d50 + '5';
        cAdd("const 1", y.cnst(1));
        cAdd("const abc", y.cnst("abc"));

        cAdd("if*short", y.exIf(y.cnst(true), y.cnst("then ..."), y.cnst("else ...")));
        cAdd("if*medium", y.exIf(y.cnst(false), y.cnst("if ? then ..."), y.cnst("if ? else ...")));
        cAdd("if*long", y.exIf(y.cnst(false), y.cnst("if ? then ..."), y.cnst("if ? else " + d50)));

        cAdd("assign*short", y.ass(y.ass(y.cf(), y.cnst(1), y.cnst("eins")), y.cnst(2), y.cnst("zwei")));
        cAdd("assign*longShort", y.ass(y.ass(y.cf(), y.cnst(1), y.cnst("eins" + d50)), y.cnst(2), y.cnst("zwei")));
        cAdd("assign*ShortLong", y.ass(y.ass(y.cf(), y.cnst(1), y.cnst("eins")), y.cnst(2), y.cnst("zwei" + d50)));
        cAdd("assign*longLong", y.ass(y.ass(y.cf(), y.cnst(1), y.cnst("eins" + d50)), y.cnst(2), y.cnst("zwei" + d50)));

        cAdd("seq*short", y.seq(y.cnst("eins"), y.cnst("zwei"), y.cnst("drei")));
        cAdd("seq*long ", y.seq(y.cnst("eins"), y.cnst("zwei"), y.cnst("drei " + d50)));
        cAdd("seq*nest ", y.seq(y.cnst("eins"), y.exIf(y.cnst(20), y.seq(y.cnst("einUndZwanzig"), y.cnst(22), y.cnst("23 " + d50), y.exIf(y.cnst(24), y.seq(y.cnst(241), y.cnst("242" + d50)), y.seq(y.cnst(251), y.cnst(252)))), y.cnst(30)), y.cnst("drei")));
        return "format5";
    }

    public void format5() {
        testFormat(cFormat() 
        , "const 1 ==> 1"
        , "const abc ==> \"abc\""
        , "if*short ==> if true then \"then ...\" else \"else ...\" endif"
        , "if*medium ==> if false then \"if ? then ...\""
        , "else \"if ? else ...\""
        , "endif"
        , "if*long ==> if false then"
        , "   \"if ? then ...\""
        , "else"
        , "   \"if ? else .........1.........2.........3.........4.........5\""
        , "endif"
        , "assign*short ==> (cf[1] = \"eins\")[2] = \"zwei\""
        , "assign*longShort ==> (cf[1] = \"eins.........1.........2.........3.........4.........5\")"
        , "   [2] = \"zwei\""
        , "assign*ShortLong ==> (cf[1] = \"eins\")[2]"
        , "   = \"zwei.........1.........2.........3.........4.........5\""
        , "assign*longLong ==> (cf[1] = \"eins.........1.........2.........3.........4.........5\")"
        , "   [2] = \"zwei.........1.........2.........3.........4.........5\""
                , "seq*short ==> \"eins\"; \"zwei\"; \"drei\""
        , "seq*long  ==> \"eins\";"
        , "\"zwei\";"
        , "\"drei .........1.........2.........3.........4.........5\""
        , "seq*nest  ==> \"eins\";"
        , "if 20 then"
        , "   \"einUndZwanzig\";"
        , "   22;"
        , "   \"23 .........1.........2.........3.........4.........5\";"
        , "   if 24 then"
        , "      241;"
        , "      \"242.........1.........2.........3.........4.........5\""
        , "   else"
        , "      251; 252"
        , "   endif"
        , "else"
        , "   30"
        , "endif;"
        , "\"drei\""
        );
    }

    public void flow() {
        begin("flow", "flowNormal u=normal, isNormal=true, isReturn=false, isThrow=false", "flowReturn u=return, isNormal=false, isReturn=true, isThrow=false", "flowThrow  u=throw , isNormal=false, isReturn=false, isThrow=true"
        );
        Flow f = Flow.normal("normal");
        out("flowNormal u=" + f.u() + ", isNormal=" + f.isNormal() + ", isReturn=" + f.isReturn() + ", isThrow=" + f.isThrow());
        f = Flow.ret("return");
        out("flowReturn u=" + f.u() + ", isNormal=" + f.isNormal() + ", isReturn=" + f.isReturn() + ", isThrow=" + f.isThrow());
        f = Flow.thrw("throw ");
        out("flowThrow  u=" + f.u() + ", isNormal=" + f.isNormal() + ", isReturn=" + f.isReturn() + ", isThrow=" + f.isThrow());
        end();
    }

    public String cConst() {
        cClear();
        cAdd("const", y.cnst("wert der Konstanten"));
        cAdd("const", y.cnst(1234));
        cAdd("const", y.cnst(false));
        cAdd("return", y.ret(y.cnst("returnValue1")));
        cAdd("throw", y.thrw(y.cnst("throwValue1")));
        cAdd("flow nor", y.cnst("flow normal"));
        cAdd("flow throw", y.thrw(y.cnst("flow throw")));
        cAdd("flow return", y.ret(y.cnst("flow return")));
        return "const";
    }
    public void exConst() {
        testExe(null, null, cConst(), "const ==> FlowNormal:\"wert der Konstanten\"", "const ==> FlowNormal:1234", "const ==> FlowNormal:false", "return ==> FlowReturn:\"returnValue1\"", "throw ==> FlowThrow:\"throwValue1\"", "flow nor ==> FlowNormal:\"flow normal\"", "flow throw ==> FlowThrow:\"flow throw\"", "flow return ==> FlowReturn:\"flow return\""
        );
    }

    public String cIf() {
        cClear();
        cAdd("if true", y.exIf(y.cnst(true), y.cnst("if ? then ..."), y.cnst("if ? else ...")));
        cAdd("if false", y.exIf(y.cnst(false), y.cnst("if ? then ..."), y.cnst("if ? else ...")));
        cAdd("if false,true", y.exIf(y.cnst(false), y.ret("if ? then ..."), y.exIf(y.cnst(true), y.ret("if false else if true..."), y.ret("if false false"))));
        cAdd("if string", y.exIf(y.cnst("string"), y.cnst("if ? then ..."), y.cnst("if ? else ...")));
        cAdd("if throw", y.exIf(y.thrw("throwing"), y.cnst("if ? then ..."), y.cnst("if ? else ...")));        
        return "ExIf";
    }

    public void exIf() {
        String n = cIf();
        testFormat(n
            , "if true ==> if true then \"if ? then ...\""
            , "else \"if ? else ...\""
            , "endif"
            , "if false ==> if false then \"if ? then ...\""
            , "else \"if ? else ...\""
            , "endif"
            , "if false,true ==> if false then"
            , "   return \"if ? then ...\""
            , "else"
            , "   if true then return \"if false else if true...\""
            , "   else return \"if false false\""
            , "   endif"
            , "endif"
            , "if string ==> if \"string\" then \"if ? then ...\""
            , "else \"if ? else ...\""
            , "endif"
            , "if throw ==> if throw \"throwing\" then \"if ? then ...\""
            , "else \"if ? else ...\""
            , "endif");
        testExe(null, null, n, "if true ==> FlowNormal:\"if ? then ...\"", "if false ==> FlowNormal:\"if ? else ...\"", "if false,true ==> FlowReturn:\"if false else if true...\"", "if string ==> FlowThrow:\"if cond string not boolean\"", "if throw ==> FlowThrow:\"throwing\""
        );
    }

    public String cMap() {
        cClear();
        Ex ass = y.ass(y.ass(y.cf(), y.cnst(1), y.cnst("eins")), y.cnst(2), y.cnst("zwei"));
        cAdd("empty get 1", y.get(y.cf(), y.cnst(1)));
        cAdd("Ass new 1->eins, 2->zwei", ass);
        cAdd("cf get 1", y.get(y.cf(), y.cnst(1)));
        cAdd("get 2", y.get(y.cf(), y.cnst(2)));
        cAdd("get 99", y.get(y.cf(), y.cnst(99)));
        cAdd("cf get 1[1]", y.get(y.get(y.cf(), y.cnst(1)), y.cnst(1)));
        cAdd("ass m := new [11:=, 12:=][13]", y.get(y.ass(y.ass(y.get(y.ass(y.cf(), y.cnst("m"), y.exNew()), y.cnst("m")), y.cnst(11), y.cnst("elf")), y.cnst(12), y.cnst("zwoelf")), y.cnst(13)));
        cAdd("get m.11", y.get(y.get(y.cf(), y.cnst("m")), y.cnst(11)));
        return "ExMap";
    }
    
    public void exMap() {
        testExe((Frame) y.nf().exe(null).u(), null, cMap(), "empty get 1 ==> FlowThrow:\"ExGet no key 1 in map {}\"", "Ass new 1->eins, 2->zwei ==> FlowNormal:{1=eins, 2=zwei}", "cf get 1 ==> FlowNormal:\"eins\"", "get 2 ==> FlowNormal:\"zwei\"", "get 99 ==> FlowThrow:\"ExGet no key 99 in map {1=eins, 2=zwei}\"", "cf get 1[1] ==> FlowThrow:\"get map eins not a Map\"", "ass m := new [11:=, 12:=][13] ==> FlowThrow:\"ExGet no key 13 in map {11=elf, 12=zwoelf}\"", "get m.11 ==> FlowNormal:\"elf\""
        );
    }

    public String cCF() {
        cClear();
        Ex ass = y.ass(y.ass(y.cf(), y.cnst(1), y.cnst("eins")), y.cnst(2), y.cnst("zwei"));
        cAdd("Ass cf 1->eins, 2->zwei", ass);
        cAdd("get cf 1", y.get(y.cf(), y.cnst(1)));
        cAdd("get cf 2", y.get(y.cf(), y.cnst(2)));
        cAdd("get cf 99", y.get(y.cf(), y.cnst(99)));
        cAdd("Ass cf nullString -> null", y.ass(y.cf(), y.cnst("nullString"), y.cnst(null)));
        cAdd("get cf nullString", y.get(y.cf(), y.cnst("nullString")));     
        return "ExCF";
    }
    public void exCF() {
        Frame cf = new Frame();
        Flow f = y.cf().exe(cf);       
        testExe(cf, i -> {out("ExCF.exe " + f + " u.class=" + f.u().getClass()); return "";},
            cCF(), "ExCF.exe FlowNormal:{} u.class=class ch.wlkl.wsm.Frame", "Ass cf 1->eins, 2->zwei ==> FlowNormal:{1=eins, 2=zwei}", "get cf 1 ==> FlowNormal:\"eins\"", "get cf 2 ==> FlowNormal:\"zwei\"", "get cf 99 ==> FlowThrow:\"ExGet no key 99 in map {1=eins, 2=zwei}\"", "Ass cf nullString -> null ==> FlowNormal:{1=eins, 2=zwei, nullString=null}", "get cf nullString ==> FlowNormal:null"
        );
    }

    public void jFun() {
        begin("jFun", "eval 0: eval() a: null", "eval clone: eval() a: len=4, [null, null, null, null]", "eval clone/putted: eval() a: len=4, [123456, null, 22, null]", "eval 0: eval() a: null", "--- error FunJava<Integer> put(3, sdf) caught ---------", "  <<<info: ArrayStoreException-java.lang.String@1 >>>");
        JFun<Integer> t = new JFun<Integer>(Integer.class) {
            public Object eval() {
                return "eval() a: " + (a == null ? a : "len=" + a.length + ", " + Arrays.deepToString(a));
            }
        };
        out("eval 0: " + t.eval());
        JFun<Integer> c = t.clone(4);
        out("eval clone: " + c.eval());
        c.put(0, 123456);
        c.put(2, 22);
        out("eval clone/putted"
                + ": " + c.eval());
        out("eval 0: " + t.eval());
        c.put(2, 109);
        c.put(3, "sdf"); // illegal
        end();
    }

    public void exDet() {
        begin("exDet", "-exe depth 1 exe=FlowThrow:\"ExDet cannot exe()\"", "    fun(1).exe(null)=FlowNormal:\"constDepth 1\"", "    fun(2).exe(null)=FlowThrow:\"ExDet cannot exe()\"", "-if exe dep1 exe=FlowThrow:\"ExDet cannot exe()\"", "    fun(1).exe(null)=FlowNormal:\"constDepth 1\"", "    fun(2).exe(null)=FlowThrow:\"ExDet cannot exe()\""
        );
        implement("det" /*
                Ex ex = y.det(y.cnst("constDepth 1"));
        toOut("-exe depth 1 exe=" + ex.exe(null)).toOut("    fun(1).exe(null)=" + ex.fun(null, 1).exe(null)).toOut("    fun(2).exe(null)=" + ex.fun(null, 2).exe(null));
        ex = y.exIf(y.cnst(true), ex, y.cnst("else"));
        toOut("-if exe dep1 exe=" + ex.exe(null)).toOut("    fun(1).exe(null)=" + ex.fun(null, 1).exe(null)).toOut("    fun(2).exe(null)=" + ex.fun(null, 2).exe(null));
        end();
         */);
    }

    public void jFuns(int wh) {
        if (wh < 10) {
            return;
        }
        y.jFunAdd("inc", new JFun<Integer>(Integer.class) {
            public Object eval() {
                return a[0] + 1;
            }
        });
        if (wh < 20) {
            return;
        }
        y.jFunAdd("equals", new JFun<Object>(Object.class) {
            public Object eval() {
                return a[0].equals(a[1]);
            }
        ;
        });
        y.jFunAdd("not", new JFun<Boolean>(Boolean.class) {
            public Object eval() {
                return !a[0];
            }
        ;
        });
        y.jFunAdd("out", new JFun<Object>(Object.class) {
            public Object eval() {
                out("  jFun#out(" + a[0] + ")");
                return 0;
            }
        ;
        });

        y.jFunAdd("ou2", new JFun<Object>(Object.class) {
            public Object eval() {
                out("  jFun#ou2(" + a[0] + ", " + a[1] + ")");
                return 0;
            }
        ;
        });
        y.jFunAdd("ou3", new JFun<Object>(Object.class) {
            public Object eval() {
                out("  jFun#ou3(" + a[0] + ", " + a[1] + ", " + a[2] + ")");
                return 0;
            }
        ;
        });

        y.jFunAdd("cat", new JFun<Object>(Object.class) {
            public Object eval() {
                return "" + a[0] + " " + a[1];
            }
        ;
        });
        
        y.jFunAdd("ca3", new JFun<Object>(Object.class) {
            public Object eval() {
                return "" + a[0] + " " + a[1] + " " + a[2];
            }
        ;
        });
    }
    
    public void testExe(Frame cf, Function<String, String> f, String nm, String... cmp) {
        begin(nm, cmp);
        if (f != null)
            f.apply("");
        for (int cx=0; cx < cName.size(); cx++) {
            out(cName.get(cx) + " ==> " + cEx.get(cx).exe(cf));
        }
        end();
    }
    
    public void cSeq() {
        cClear();
        jFuns(10);
        cAdd("Ass cf 1->eins; 2->zwei; get 2", y.seq(y.ass(y.cf(), y.cnst(1), y.cnst("eins")), y.ass(y.cf(), y.cnst(2), y.cnst("zwei")), y.get(y.cf(), y.cnst(2))));
        cAdd("Ass cf map -> [10>Zehn, 11->Elf]; get[cf,map,11]", y.seq(y.ass(y.cf(), y.cnst("map"), y.exNew()), y.ass(y.ass(y.get(y.cf(), y.cnst("map")), y.cnst(10), y.cnst("Zehn")), y.cnst(11), y.cnst("Elf")), y.get(y.get(y.cf(), y.cnst("map")), y.cnst(11))));
        JFun f = new JFun<Integer>(Integer.class) {
            public Object eval() {
                return "" + a[0] + '+' + a[1] + " = "
                        + ((Integer) a[0] + (Integer) a[1]);
            }
        };
        f.name = "plusEqInt";
        cAdd("ExJava 1+2", y.jFun(f, y.cnst(1), y.cnst(2)));
        f = new JFun<Integer>(Integer.class) {
            public Object eval() {
                return "" + a[0] + '+' + a[1] + " = " + (a[0] + a[1]);
            }};
        f.name = "plusEqObj";
        cAdd("ExJava 1+2", y.jFun(f, y.cnst(1), y.cnst(2)));
        f = new JFun<String>(String.class) {
            public Object eval() {
                return a[0] + " + " + a[1];
            }
        };
        f.name = "plus";
        cAdd("ExJava cf[1]+cf[2]", y.jFun(f, y.get(y.cf(), y.cnst(1)), y.get(y.cf(), y.cnst(2))));

        y.jFunAdd("<5", new JFun<Integer>(Integer.class) {
            public Object eval() {
                return a[0] < 5;
            }
        });
        y.jFunAdd("*2", new JFun<Integer>(Integer.class) {
            public Object eval() {
                return a[0] * 2;
            }
        });
        cAdd("ExSeq while ix < 5 do p*=2", y.seq(y.ass(y.ass(y.cf(), y.cnst("ix"), y.cnst(1)), y.cnst("p"), y.cnst(2)), y.whl(y.jFun("<5", y.get(y.cf(), y.cnst("ix"))), y.ass(y.ass(y.cf(), y.cnst("ix"), y.jFun("inc", y.get(y.cf(), y.cnst("ix")))), y.cnst("p"), y.jFun("*2", y.get(y.cf(), y.cnst("p"))))), y.get(y.cf(), y.cnst("p"))));
    }


    public void exSeq() {
        cSeq();
        testFormat("formatSeq", "Ass cf 1->eins; 2->zwei; get 2 ==> cf[1] = \"eins\"; cf[2] = \"zwei\"; cf[2]", "Ass cf map -> [10>Zehn, 11->Elf]; get[cf,map,11] ==> cf[\"map\"] = new;", "(cf[\"map\"][10] = \"Zehn\")[11] = \"Elf\";", "cf[\"map\"][11]", "ExJava 1+2 ==> plusEqInt(1, 2)", "ExJava 1+2 ==> plusEqObj(1, 2)", "ExJava cf[1]+cf[2] ==> plus(cf[1], cf[2])", "ExSeq while ix < 5 do p*=2 ==> (cf[\"ix\"] = 1)[\"p\"] = 2;", "while <5(cf[\"ix\"]) do", "   (cf[\"ix\"] = inc(cf[\"ix\"]))[\"p\"] = *2(cf[\"p\"])", "endwhile;", "cf[\"p\"]"
        );
        testExe(new Frame(), null,"exSeq", "Ass cf 1->eins; 2->zwei; get 2 ==> FlowNormal:\"zwei\"", "Ass cf map -> [10>Zehn, 11->Elf]; get[cf,map,11] ==> FlowNormal:\"Elf\"", "ExJava 1+2 ==> FlowNormal:\"1+2 = 3\"", "ExJava 1+2 ==> FlowNormal:\"1+2 = 3\"", "ExJava cf[1]+cf[2] ==> FlowNormal:\"eins + zwei\"", "ExSeq while ix < 5 do p*=2 ==> FlowNormal:32"
        );
    }

    public void exCall() {
        begin("exCall", "vorher bf e12: FlowThrow:\"ExGet no key 2 in map {1=baseFrameEins}\"", "call fun e12 c1Eins, c1Zwei :FlowNormal:\"1=c1Eins, 2=c1Zwei\"", "mitte bf e12: FlowThrow:\"ExGet no key 2 in map {1=baseFrameEins}\"", "call fun12 c2eins, c2Zweitens :FlowNormal:\"1=c2eins, 2=c2Zweitens\"", "ende bf e12: FlowNormal:\"1=baseFrameEins, 2=baseFrameZwei\""
        /*                , "curry fun<curry>2 curryEins1, curriedEins2 :FlowNormal:\"1=curryEins1, 2=curriedEins2\""
                , "curry fun<curryZwei> curryZwei1, curriedZwei2 :FlowNormal:\"1=curryZwei1, 2=curriedZwei2\""
                , "curry fun<curryZwei> curryZwei1, curriedDrei2 :FlowNormal:\"1=curryZwei1, 2=curriedDrei2\""
                , "endeCurry bf e12: FlowNormal:\"1=baseFrameEins, 2=baseFrameZwei\""
                , "return from loopFlowNormal:\"returning 37\""
         */);
        y.jFunAdd("o12", new JFun<String>(String.class) {
            public Object eval() {
                return "1=" + a[0] + ", 2=" + a[1];
            }
        });
        Frame bf = new Frame();
        Ex e12 = y.jFun("o12", y.get(y.cf(), y.cnst(1)), y.get(y.cf(), y.cnst(2)));
        out("vorher bf e12: " + y.seq(y.ass(y.cf(), y.cnst(1), y.cnst("baseFrameEins")), e12).exe(bf));
        out("call fun e12 c1Eins, c1Zwei :" + y.call(y.cnst(e12), y.ass(y.ass(y.nf(), y.cnst(1), y.cnst("c1Eins")), y.cnst(2), y.cnst("c1Zwei"))).exe(bf));
        out("mitte bf e12: " + e12.exe(bf));
        out("call fun12 c2eins, c2Zweitens :" + y.seq(y.ass(y.ass(y.cf(), y.cnst("fun12"), y.cnst(e12)), y.cnst(2), y.cnst("baseFrameZwei")), y.call(y.get(y.cf(), y.cnst("fun12")), y.ass(y.ass(y.nf(), y.cnst(1), y.cnst("c2eins")), y.cnst(2), y.cnst("c2Zweitens")))).exe(bf));
        out("ende bf e12: " + e12.exe(bf));
        /*        toOut("curry fun<curry>2 curryEins1, curriedEins2 :" + y.seq(y.ass(y.cf(), y.cnst("curry2")
                    , y.fun(y.fun(y.call(y.det(y.det(y.fun(e12))), y.ass(y.nf(), y.cnst(1), y.det(y.get(y.cf(), y.cnst(1))), y.cnst(2), y.get(y.cf(),y.cnst(2)))))))
                    , y.call(y.call(y.get(y.cf(), y.cnst("curry2")), y.ass(y.nf(), y.cnst(1), y.cnst("curryEins1"))), y.ass(y.nf(), y.cnst(2), y.cnst("curriedEins2"))
                )).exe(bf));
        toOut("curry fun<curryZwei> curryZwei1, curriedZwei2 :" + y.seq(y.ass(y.cf(), y.cnst("curryZwei")
                , y.call(y.get(y.cf(), y.cnst("curry2")), y.ass(y.nf(), y.cnst(1), y.cnst("curryZwei1"))))
                , y.call(y.get(y.cf(), y.cnst("curryZwei")), y.ass(y.nf(), y.cnst(2), y.cnst("curriedZwei2"))
            )).exe(bf));
        toOut("curry fun<curryZwei> curryZwei1, curriedDrei2 :" + 
                y.call(y.get(y.cf(), y.cnst("curryZwei")), y.ass(y.nf(), y.cnst(2), y.cnst("curriedDrei2"))
            ).exe(bf));
        toOut("endeCurry bf e12: " + e12.exe(bf));
        toOut("return from loop" + y.call(y.fun(y.seq(y.whl(y.jFun("<5", y.get(y.cf(), y.cnst("jx"))) 
            , y.seq(y.ass(y.cf(), y.cnst("ix"), y.jFun("inc", y.get(y.cf(), y.cnst("ix"))))
                    , y.exIf(y.jFun("<5", y.get(y.cf(), y.cnst("ix"))), y.cnst(null), y.ret(y.cnst("returning 37")))))
            , y.cnst("after while loop"))), y.ass(y.nf(), y.cnst("ix"), y.cnst(1), y.cnst("jx"), y.cnst(1))).exe(bf));
         */ end();
    }

    public void exTry() {
        Frame bf = new Frame();
        begin("exTry", "try ... catch: FlowNormal:\"caught catchVar=throwEins\""
        );
        y.jFunAdd("catchVar", new JFun<String>(String.class) {
            public Object eval() {
                return "caught catchVar=" + a[0];
            }
        });
        out("try ... catch: " + y.seq(y.cnst("vorher0"), y.exTry(y.seq(y.cnst("vorher10"), y.thrw(y.cnst("throwEins")), y.thrw(y.cnst("throwZwei")), y.cnst("nachher 12")), y.cnst("catchVar"), y.jFun("catchVar", y.get(y.cf(), y.cnst("catchVar"))))).exe(bf));
        end();
    }

    public void parse() {
        begin("parser", "stringli 1 true: \"stringli oder ?\", xUnquote <stringli oder ?>", "stringli 2 true: \"stringli oder ?\", xUnquote <stringli oder ?>", "stringli 3 true: \"stringli \\\" oder ?\", xUnquote <stringli \" oder ?>", "stringli 4 true: \"stringli \\\"oder\\\" oder\\\" back\\\\slash ?\", xUnquote <stringli \"oder\" oder\" back\\slash ?>", "name true: wie", "name false: null", "nlComment true", "name true: gehts", "nlComment true", "name false: null", "number true: 123", "skip.number false: null", "string true: \"a\\\"\\\\b\\\"c  \"", "skip.name true: oder", "skip.name false: null", "end false: null", "chars 1 true: ?", "end true: ?"
        );
        Parser p = new Parser("\"stringli oder ?\" und ");
        out("stringli 1 " + p.next(p.string) + ": " + p.tok + ", xUnquote <" + p.xUnquote(p.tok) + ">");
        p = new Parser("\"stringli oder ?\" und\" ");
        out("stringli 2 " + p.next(p.string) + ": " + p.tok + ", xUnquote <" + p.xUnquote(p.tok) + ">");
        p = new Parser("\"stringli \\\" oder ?\" und\" ");
        out("stringli 3 " + p.next(p.string) + ": " + p.tok + ", xUnquote <" + p.xUnquote(p.tok) + ">");
        p = new Parser("\"stringli \\\"oder\\\" oder\\\" back\\\\slash ?\" und\" ");
        out("stringli 4 " + p.next(p.string) + ": " + p.tok + ", xUnquote <" + p.xUnquote(p.tok) + ">");
        p = new Parser("wie gehts \t\n     123 \"a\\\"\\\\b\\\"c  \" oder?");
        out("name " + p.next(p.name) + ": " + p.tok);
        out("name " + p.next(p.name) + ": " + p.tok);
        out("nlComment " + p.spaceNlComment());
        out("name " + p.next(p.name) + ": " + p.tok);
        out("nlComment " + p.spaceNlComment());
        out("name " + p.next(p.name) + ": " + p.tok);
        out("number " + p.next(p.number) + ": " + p.tok);
        out("skip.number " + p.skip().next(p.number) + ": " + p.tok);
        out("string " + p.next(p.string) + ": " + p.tok);
        out("skip.name " + p.skip().next(p.name) + ": " + p.tok);
        out("skip.name " + p.skip().next(p.name) + ": " + p.tok);
        out("end " + p.end() + ": " + p.tok);
        out("chars 1 " + p.lit("?") + ": " + p.tok);
        out("end " + p.end() + ": " + p.tok);
        end();
    }

    public void cmp(String text, String src) {
        Ex e = compiler.compile(src);
        if (false) {
            out("compile: " + src + "\n==> " + e.format());
        }
        Flow f = e.exe(bf);
        out(text + f);
    }

    public void compBase() {
        begin("compile", "abc FlowNormal:\"abc \\\" efg\"", "123 FlowNormal:123", "if equals(1,1)  FlowNormal:\"then true\"", "if equals(1,2)  FlowNormal:\"else false..............................................\"", "cf[1 := eins ]  FlowNormal:{1=eins}", "cf[1]           FlowNormal:\"eins\"", "cf[3]           FlowThrow:\"ExGet no key 3 in map {1=eins}\"", "cf[2:=][3:=][2] FlowNormal:\"zwei\"", "cf[1]           FlowNormal:\"eins\"", "cf[3]           FlowNormal:\"drei\"", "cf[9 := new ...]FlowNormal:992", "begin cf[9][2]  FlowNormal:92", "beg cf[9][9][1] FlowNormal:991", "  jFun#out(1)", "  jFun#out(2)", "while 1..3      FlowNormal:0", "  jFun#out(fun7)", "  jFun#out(arg0 in call eins)", "  jFun#out(fun7)", "  jFun#out(arg0 in call zwei)", "call.....       FlowNormal:\"vorher\"", "  jFun#ou3(1, 11, elf)", "  jFun#ou3(2, 12, zwoelf)", "for 121 in [121]FlowNormal:12", "cf[11 := fun    FlowNormal:\"return fun11 eins\"", "cf[11](in := 2) FlowNormal:\"return fun11 zwei\"", "cf[11](in := 3) FlowThrow:\"throw fun11 drei\"", "cf[11](in := 9) FlowThrow:\"throw fun11 else\"", "  jFun#ou2(trying, return fun11 eins)", "try 1 catch     FlowNormal:\"try last\"", "  jFun#ou2(catched, throw fun11 drei)", "try 3 catch     FlowNormal:\"handler last\""
        /*                , "  jFun#ou2(cf[0], secondCa0)"
                , "  jFun#ou2(det cf[1], firstCa1)"
                , "  jFun#ou2(det det cf[2], main2)"
                , "fun---exe       FlowNormal:inner funEnd" */
        );
        y = compiler.factory;
        cmp("abc ", " \"abc \\\" efg\"  ");
        cmp("123 ", "; \"qrst \";; 123 ; ;  ");
        jFuns(20);
        cmp("if equals(1,1)  ", "; if equals(1,1) then \"then true\" else \"else false\" ;;; ifEnd ;;;");
        cmp("if equals(1,2)  ", "; if equals(1,2) then \"then true\" else \"else false..............................................\" ;;; ifEnd ;;;");
        cmp("cf[1 := eins ]  ", "cf  [  1     := \"eins\"  ]  ");
        cmp("cf[1]           ", "cf  [  1  ]   ");
        cmp("cf[3]           ", "cf[3]");
        cmp("cf[2:=][3:=][2] ", "cf  [  2     := \"zwei\"  ] [  3     := \"drei\"  ]  [2]");
        cmp("cf[1]           ", "cf  [  1  ]   ");
        cmp("cf[3]           ", "cf[3]");
        cmp("cf[9 := new ...]", "cf[9 := new [1:=91][9:= new[1:=991][2:=992]][2:=92]][9][9][2]");
        cmp("begin cf[9][2]  ", "begin ;;; cf[9][2]  ;;; end");
        cmp("beg cf[9][9][1] ", "begin cf[9][9][1] end");
        cmp("while 1..3      ", "cf[7:=0]; while cf[7 := inc(cf[7])];not(equals(cf[7], 3)) do   out(cf[7]) wEnd");
        cmp("call.....       ", "cf[\"arg0\" := \"vorher\"];cf[7:= fun out(\"fun7\"); out(cf[\"arg0\"]); funEnd ]; cf[7](\"arg0\" := \"arg0 in call eins\");cf[7](\"arg0\" := \"arg0 in call zwei\");cf[\"arg0\"]");
        cmp("for 121 in [121]", "cf[123 := 0, 121 := new [11 := \"elf\", 12 := \"zwoelf\"]];for 122 in cf[121] do cf[123 := inc(cf[123])]; ou3(cf[123],  cf[122], cf[121][cf[122]]) forEnd; cf[122]");
        cmp("cf[11 := fun    ", "cf[11:=fun if equals(cf[\"in\"], 1) then return \"return fun11 eins\" "
                + "elif equals(cf[\"in\"], 2) then return \"return fun11 zwei\" "
                + "elif equals(cf[\"in\"], 3) then throw \"throw fun11 drei\" ; "
                + "else throw \"throw fun11 else\" ifEnd; \"end of fun11\"; funEnd]; "
                + "cf[11](\"in\" := 1)");
        cmp("cf[11](in := 2) ", "cf[11](\"in\" := 2)");
        cmp("cf[11](in := 3) ", "cf[11](\"in\" := 3)");
        cmp("cf[11](in := 9) ", "cf[11](\"in\" := 9 , 5 :=55   )");
        cmp("try 1 catch     ", "try ou2(\"trying\", cf[11](\"in\" := 1  )); \"try last\";; catch 12 handle ou2(\"catched\", cf[12]);; \"handler last\" tryEnd;");
        cmp("try 3 catch     ", "try ou2(\"trying\", cf[11](\"in\" := 3  )); \"try last\";; catch 12 handle ou2(\"catched\", cf[12]);; \"handler last\" tryEnd;");
        cmp("fun---exe       ", "cf[0 := \"main0\",1 := \"main1\",2 := \"main2\"]; " +
                "fun fun ou2(\"cf[0]\", cf[0]); ou2(\"det cf[1]\", det cf[1] detEnd); ou2(\"det det cf[2]\", det det cf[2] detEnd detEnd); \"inner funEnd\" funEnd funEnd " +
                "(0 := \"firstCa0\",1 := \"firstCa1\",2 := \"firstCa2\")  " +
                "(0 := \"secondCa0\",1 := \"secondCa1\",2 := \"secondCa2\")");
        end();
    }

    public void compCurry() {
        Ex ex = null;
        y = compiler.factory;
        jFuns(20);
        begin("compCurry", "fun11       FlowNormal:\"fun11: arg0 arg1\"", "curry0      FlowNormal:\"fun11: curry0Map0 call2arg1\"", "curry0 plus FlowNormal:\"fun11: curry0Map0 callPlusarg1\"", "curry2      FlowNormal:\"fun11: curry2Map0 call2arg1\"", "curry3      FlowNormal:\"fun11: curry3Map0 3call2arg1\"", "curry3 :=   FlowNormal:\"fun11: curry3Map0Modified 3call2arg1\"", "curry3    1 FlowNormal:\"fun11: 3call2arg0 curry3Map1\"", "curry4      FlowNormal:\"fun11: curry4map0 call2arg1\""
        );
        cmp("fun11       ", "cf[11 := fun return ca3(\"fun11:\", cf[0], cf[1]) funEnd]; cf[11](0 := \"arg0\", 1 := \"arg1\")");
        // curry0(fun := o2s, 0:= z) ==> o2s(0 := z, .....) simply transfer argument 0
        cmp("curry0      ", "cf[\"curry0\" := fun fun cf[0 := det cf[0] detEnd]; exe det cf[\"fun\"] detEnd exeEnd funEnd funEnd"
                + ", 12 := cf[\"curry0\"](\"fun\" := cf[11], 0 := \"curry0Map0\")]; "
                + "cf[12] (1 := \"call2arg1\")");
        cmp("curry0 plus ", "cf[12] (1 := \"callPlusarg1\")");
        // curry2(fun := o2s, map := m) ==> o2s(0 := m[0], .....) transfer arguments in map m[0]
        cmp("curry2      ", "cf[\"curry2\" := fun fun cf[0 := det cf[\"map\"] [0] detEnd ]; exe det cf[\"fun\"] detEnd exeEnd funEnd funEnd"
                + ", 22 := cf[\"curry2\"](\"fun\" := cf[11], \"map\" := new[0 := \"curry2Map0\"])]; "
                + "cf[22] (1 := \"call2arg1\")");
        // curry3: (fun := o2s) ==> o2s(m, .....) transfer all arguments in a2s given map m
        cmp("curry3      ", "cf[33 := new [0 := \"curry3Map0\"]];"
                + "cf[\"curry3\" := fun cf[0 := new]; fun for det cf[0] detEnd in det cf[\"map\"] detEnd do cf[cf[det cf[0] detEnd] := det cf[\"map\"] detEnd [ cf[det cf[0] detEnd ]]] forEnd; exe det cf[\"fun\"] detEnd exeEnd funEnd funEnd];"
                + "cf[31 := cf[\"curry3\"](\"fun\" := cf[11], \"map\" := cf[33])];"
                + "cf[31](1 := \"3call2arg1\")");
        cmp("curry3 :=   ", "cf[33][0:= \"curry3Map0Modified\"]; cf[31](1 := \"3call2arg1\")");
        cmp("curry3    1 ", "cf[\"curry3\"](\"fun\" := cf[11], \"map\" := new[1 := \"curry3Map1\"])(0 := \"3call2arg0\")");
        // curry4: (fun := o2s) ==> o2s(m, .....) with a2s given map m
        cmp("curry4      ", "cf[\"curry4\" := fun cf[0 := fun ;funEnd]; "
                + "for 1 in cf[\"map\"] do cf[0 := fun exe det cf[0] detEnd exeEnd; cf[det cf[1] detEnd := det cf[\"map\"][cf[1]] detEnd ] funEnd] forEnd; "
                + "fun exe det cf[0] detEnd exeEnd; exe det cf[\"fun\"] detEnd exeEnd funEnd funEnd];"
                + "cf[\"curry4\"](\"fun\" := cf[11], \"map\" := new[0 := \"curry4map0\"])(1 := \"call2arg1\")");
        end();
    }

    public void compile(AbstractCompiler ac) {
        compiler = ac;
        bf = new Frame();
        compBase();
        /*        bf = new Frame();
        compCurry();
         */    }

    public void testAll(String name, Function<String, String> f) {
        f.apply(cConst());
        f.apply(cFormat());
        f.apply(cConst());
        f.apply(cIf());
        f.apply(cMap());
        f.apply(cCF());
//        o2s.apply(cFun());
    }
    public void testAll() {
        debugLevel = -1;
        test("wsm.Test All"
                
            , t -> formatSimple()
            , t -> formatMake()
            , t -> testAll("format", n -> {sayFormat(n); return "";})
            , t -> format5()
            , t -> flow()
            , t -> exConst()
            , t -> exIf()
            , t -> exMap()
            , t -> exCF()
            , t -> jFun()
            , t -> exSeq()
            , t -> exCall()
            , t -> exTry()
            , t -> parse()
            , t -> compile(new Compiler())
            , t -> compile(new CompilerWSM())
            );
    }

    public void test () {
        test(t -> compile(new CompilerWSM()));
        
    }
    public static void main(String... args) {
        new Test().testAll();
    }
}