java/ch/wlkl/wsm/CompilerWSM.java

package ch.wlkl.wsm;

import static ch.wlkl.env.Env.*;
import java.util.ArrayList;

public class CompilerWSM extends AbstractCompiler {
    private Ex compSeq = null;
    public CompilerWSM() {
        super();
    }
    public CompilerWSM(ExFactory f) {
        super(f);
    }

    
    Ex seq() {
        if (compSeq == null)
            ini();
        Flow fl = compSeq.exe(new Frame());
        if (! fl.isNormal())
            err("seq: seq not normal: " + fl + ": source: " + src);
        Ex c = (Ex) fl.u();
        return c; 
    }
    
    void ini() {
        ExFactory y = factory;
        y.jFunAdd("null", new JFun<Object>(Object.class) {
            public Object eval() { 
                return null; 
            };});
        y.jFunAdd("isNull", new JFun<Object>(Object.class) {
            public Object eval() { 
                return a[0] == null; 
            };});
        y.jFunAdd("notNull", new JFun<Object>(Object.class) {
            public Object eval() { 
                return a[0] != null; 
            };});
        y.jFunAdd("equals", new JFun<Object>(Object.class) {
            public Object eval() { 
                return a[0].equals(a[1]); 
            };});
        y.jFunAdd("skip", new JFun<Object>(Object.class) {
            public Object eval() { 
                return skip(); 
            };});
        y.jFunAdd("const", new JFun<Object>(Object.class) {
            public Object eval() { 
                return exConst(); 
            };});
        y.jFunAdd("lit", new JFun<String>(String.class) {
            public Object eval() { 
                return lit(a[0]); 
            };});
        y.jFunAdd("name", new JFun<String>(String.class) {
            public Object eval() { 
                return name(a);
            };});
        y.jFunAdd("nextName", new JFun<String>(String.class) {
            public Object eval() { 
                return next(Parser.name) ? tok : null;
            };});
        y.jFunAdd("back", new JFun<String>(String.class) {
            public Object eval() { 
                back(); 
                return null;
            };});
        y.jFunAdd("fail", new JFun<String>(String.class) {
            public Object eval() { 
                fail(a[0]);
                return null;
            };});
/*        Ex ex = y.seq(y.jFun("skip"), y.jFun("const"));
        out("ex ==>\n" + ex.toString());
        compSeq = y.seq(
                y.ass(y.cf(), y.cnst(1), ex), 
                y.jFun("skip"),
                y.get(y.cf(), y.cnst(1)));
        out("ini compSeq ==>\n" + compSeq.toString()); */
        compSeq = new Compiler(y).compile("cf[" +
                "\"checkName\" := fun if name(cf[\"name\"]) then return cf[\"val\"] else ifEnd funEnd," +
                "\"one\" := fun skip(); " +
                    "cf[2 := const()]; if notNull(cf[2]) then return cf[2] else ifEnd;" +
                    "cf[1 := nextName()];" +
                    "if isNull(cf[1]) then null(); " +
                    "elif equals(\"if\", cf[1]) then det cf detEnd[\"checkName\"](\"val\" := det cf detEnd[\"if\"](), \"name\" := \"ifEnd\")" +
                    "else back() " +
                    "ifEnd " +
                    "funEnd," +
                "\"seq\" := fun cf[1 := det cf detEnd[\"one\"]()]; " +
                    "skip();" +
                    "if lit(\";\") then else return cf[1] ifEnd;" +
                    "cf[2 := det cf detEnd [\"seq\"] ()]; " +
                    "if isNull(cf[1]) then cf[2] elif isNull(cf[2]) then cf[1] " +
                    "else fun exe det cf[1] detEnd exeEnd; exe det cf[2] detEnd exeEnd funEnd ifEnd " +
                    "funEnd, " + 
                "\"if\" := fun " +
                    "skip();" +
                    "cf[1 := det cf detEnd [\"seq\"] ()]; if isNull(cf[1]) then fail(\"if condition expected\") else ifEnd;" +
                    "cf[2 := det cf detEnd [\"seq\"] ()]; " +
                    "if notNull(name(\"else\")) " +
                    "then return fun if exe det cf[1] detEnd exeEnd then exe det cf[2] detEnd exeEnd else exe det det cf detEnd [\"seq\"] detEnd exeEnd ifEnd funEnd;" +
                    "else fail(\"else expected\")" +
                    "ifEnd; funEnd, " +
                "\"jfun\" := fun " +
                    "if skip(); notNull(lit(\"(\")) " +
                    "then cf[2 := 0, 3 := 1];" +
                        "while equals(cf[3], 1) " +
                        "do" +
/*    Ex jfun(String fun) {
        List<Ex> exs = new ArrayList<Ex>();
        if (skip().lit("(")) {
            do {
                skip();
                Ex e1 = ex();
                if (e1 == null)
                    fail("expression expected");
                exs.add(e1);
            } while (skip().lit(","));
        checkLit(null, ")");
        }
        return factory.jFun(fun, exs.toArray(new Ex[exs.size()]));
    } */
                    "] ;" +
                "cf[\"seq\"]()" 
                );
        out("ini compile compSeq ==>\n" + compSeq.format());
    }
    
    Ex ex() {
        Ex map = exOne();
        while (true) {
            if (skip().lit("[")) 
                map = checkLit(assOrGet(map, false), "]");
            else if (lit("((")) 
                map = factory.call(map, checkLit(ex(), "))"));
            else if (lit("(")) 
                map = checkLit(assOrGet(map, true), ")");
            else
                return map;
        }
    }

    Ex assOrGet(Ex map, boolean isAss) {
        ArrayList<Ex> al = null;
        do {
            Ex val = null, ix = ex();
            if (ix == null)
                break;
            else if (skip().lit(":="))
                val = ex();
            else if (isAss || al != null)
                fail(":= in assignment expected");
            else 
                return factory.get(map, ix);
            if (al == null) 
                (al = new ArrayList<Ex>()).add(map); 
            al.add(ix);
            al.add(val);
            map = factory.ass(map, ix, ex());
        } while (skip().lit(","));
                implement("factory return" /*
        return isAss ? factory.call(al.toArray(Ex.a0)) : factory.ass(al.toArray(Ex.a0));  */ );
                return null;
    }

    Ex exOne() {
        skip();
        if (! next(name)) {
            Ex e = exConst();
            if (e != null)
                return e;
        } else if ("begin".equals(tok)) {
            return checkName(seq(), "end");
        } else if ("cf".equals(tok)) {
            return factory.cf();
                        
                } else { implement("missing factory methodss"); return null; /*        
                } else if ("det".equals(tok)) {
            return factory.det(checkName(seq(), "detEnd"));
        } else if ("exe".equals(tok)) {
            return factory.exExe(checkName(seq(), "exeEnd"));
        } else if ("for".equals(tok)) {
            return factory.exFor(checkName(ex(), "in"), checkName(ex(), "do"), checkName(seq(), "forEnd"));
        } else if ("fun".equals(tok)) {
            return factory.fun(checkName(seq(), "funEnd"));
        } else if ("if".equals(tok)) {
//            return compIf();
        } else if ("new".equals(tok)) {
            return factory.exNew();
        } else if ("return".equals(tok)) {
            return factory.ret(ex());
        } else if ("throw".equals(tok)) {
            return factory.thrw(ex());
        } else if ("try".equals(tok)) {
            return factory.exTry(checkName(seq(), "catch"), checkName(ex(), "handle"), checkName(seq(), "tryEnd"));
        } else if ("while".equals(tok)) {
            return factory.whl(checkName(seq(), "do"), checkName(seq(), "wEnd"));
        } else if (resWords.matcher(tok).matches()) { // ignore, for later usage!
        } else if (factory.jFunExists(tok)) {
//            return jfun(tok); */
        } 
        back();
        return null; 
    }
    
}