java/ch/wlkl/wsm/ExFactory.java
package ch.wlkl.wsm;
import static ch.wlkl.env.Env.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/*-------------------- abstract helpers ---------------------------------*/
/**
* an Expression with no subExpressions
*/
/*-------------------- starting points ---------------------------------*/
class ExCF extends Ex {
public Flow exe(Frame cf) {
return Flow.normal(cf);
}
public void format(Formatter f) {
}
}
class ExConst extends Ex {
final Flow con;
public ExConst(Flow pCon) {
con = pCon;
}
public Flow exe(Frame cf) {
return con;
}
public void format(Formatter f) {
f.format(1, con.uString());
}
}
class ExJFun extends Ex {
final JFun jFun;
final Ex[] exs;
public ExJFun(JFun jf, Ex... e) {
jFun = jf;
exs = e;
}
@Override
public Flow exe(Frame cf) {
JFun jf = jFun.clone(exs.length);
for (int ix = 0; ix < exs.length; ix++) {
Flow f = exs[ix].exe(cf);
if (!f.isNormal()) {
return f;
}
jf.put(ix, f.u());
}
try {
return Flow.normal(jf.eval());
} catch (Exception e) {
return Flow.thrw("ExJava jFun.doEval " + a2r("ExJava Exception: ", e));
}
}
@Override
public void format(Formatter f) {
f.format(1, jFun.name);
for (int ix=0; ix < exs.length; ix++)
f.format(2, exs[ix]);
}
}
/*
class ExJFunDyn extends ExA {
final private ExFactory factory;
public ExJFunDyn(ExFactory f, Ex... e) {
super(e);
factory = f;
if (e.length < 1)
err("missing ExJFunDyn name");
}
@Override
public Flow exe(Frame cf) {
return factory.jFun(exs[0].exe(cf), this).exe(cf);
}
public Flow fun(Frame cf, int depth) {
Flow f = super.fun(cf, depth);
if (! f.isNormal())
return f;
ExJFunDyn n = (ExJFunDyn) f.u();
return n.exs[0] instanceof ExConst ? factory.jFun(((ExConst)n.exs[0]).con, n) : f;
}
} */
/*-------------------- Maps ---------------------------------*/
class ExNew extends Ex {
public Flow exe(Frame cf) {
return Flow.normal(new HashMap<Object, Object>());
}
public void format(Formatter f) {
f.format(1);
}
}
class ExNF extends Ex {
@Override
public Flow exe(Frame cf) {
return Flow.normal(new Frame());
}
public void format(Formatter f) {
f.format(1, "newframe");
}
}
class ExGet extends Ex {
final Ex map, key;
public ExGet(Ex m, Ex k) {
map = m;
key = k;
}
@Override
public Flow exe(Frame cf) {
Flow f = map.exe(cf);
if (!f.isNormal()) {
return f;
}
Flow k = key.exe(cf);
if (!k.isNormal()) {
return k;
}
if ((f.u() instanceof Map)) {
Map m = (Map) (f.u());
if (m.containsKey(k.u())) {
return Flow.normal(m.get(k.u()));
} else {
return Flow.thrw("ExGet no key " + k.u() + " in map " + m);
}
}
return Flow.thrw("get map " + f.u() + " not a Map");
}
public void format(Formatter f) {
f.format(1, map);
f.format(2, key);
}
}
class ExAss extends Ex {
final Ex map, key, val;
public ExAss(Ex m, Ex k, Ex v) {
map = m;
key = k;
val = v;
}
@Override
public Flow exe(Frame cf) {
Flow f = map.exe(cf);
if (!f.isNormal()) {
return f;
}
Flow k = key.exe(cf);
if (!k.isNormal()) {
return k;
}
Flow v = val.exe(cf);
if (!v.isNormal()) {
return v;
}
if ((f.u() instanceof Map)) {
Map m = (Map) (f.u());
m.put(k.u(), v.u());
return f;
}
return Flow.thrw("put map " + f.u() + " not a Map");
}
public void format(Formatter f) {
f.format(1, map);
f.format(2, key);
f.format(3, val);
}
}
class ExFor extends Ex {
final Ex eFor, eIn, eDo;
public ExFor(Ex f, Ex i, Ex d) {
eFor = f;
eIn = i;
eDo = d;
}
@Override
public Flow exe(Frame cf) {
Flow f = eIn.exe(cf);
if (!f.isNormal()) {
return f;
}
if (f.u() instanceof Map) {
Map m = (Map) f.u();
Flow res = Flow.normal(null);
for (Iterator iterator = m.keySet().iterator(); iterator.hasNext();) {
Object ky = iterator.next();
Flow k = eFor.exe(cf);
if (!k.isNormal()) {
return k;
}
cf.put(k.u(), ky);
f = eDo.exe(cf);
if (!f.isNormal()) {
return f;
}
}
return f;
}
return Flow.thrw("ExFor.exe map=" + f.u() + " is not a Map");
}
public void format(Formatter f) {
f.format(1, eFor);
f.format(2, eIn);
f.format(3, eDo);
}
}
/*-------------------- control flow ---------------------------------*/
class ExIf extends Ex {
final Ex eIf, eThen, eElse;
public ExIf(Ex i, Ex t, Ex e) {
eIf = i;
eThen = t;
eElse = e;
}
@Override
public Flow exe(Frame cf) {
boolean cond;
Flow f = eIf.exe(cf);
if (!f.isNormal()) {
return f;
}
Flow r;
if (f.u().equals(true)) {
return eThen.exe(cf);
} else if (f.u().equals(false)) {
return eElse.exe(cf);
} else {
return Flow.thrw("if cond " + f.u() + " not boolean");
}
}
public void format(Formatter f) {
f.format(1, eIf);
f.format(2, eThen);
f.format(3, eElse);
}
}
class ExSeq extends Ex {
final Ex[] seq;
public ExSeq(Ex... e) {
seq = e;
}
@Override
public Flow exe(Frame cf) {
Flow f = null;
for (int sx = 0; sx < seq.length; sx++) {
f = seq[sx].exe(cf);
if (!f.isNormal()) {
return f;
}
}
return f != null ? f : Flow.normal(null);
}
public void format(Formatter f) {
for (int i = 0; i < seq.length; i++) {
f.format(1, seq[i]);
}
}
}
class ExWhile extends Ex {
final Ex eW, eDo;
public ExWhile(Ex cond, Ex st) {
eW = cond;
eDo = st;
}
@Override
public Flow exe(Frame cf) {
boolean cond;
Flow stmt = null;
while (true) {
Flow w = eW.exe(cf);
if (!w.isNormal()) {
return w;
}
boolean wb;
try {
wb = (Boolean) w.u();
} catch (Exception e) {
return Flow.thrw("while condition not boolean: " + w.u() + ": " + a2r("while condition not boolean: ", e));
}
if (!wb) {
return stmt == null ? Flow.normal(null) : stmt;
}
stmt = eDo.exe(cf);
if (!stmt.isNormal()) {
return stmt;
}
}
}
public void format(Formatter f) {
f.format(1, eW);
f.format(2, eDo);
}
}
/*--------------------
class ExFun extends Ex {
public ExFun(Ex e1) {
super(e1);
}
@Override
public Flow exe(Frame cf) {
return ex.fun(cf, 1);
}
@Override
public Flow fun(Frame cf, int depth) {
return super.fun(cf, depth+1);
}
} */
class ExCall extends Ex {
final Ex code, frame;
public ExCall(Ex c, Ex f) {
code = c;
frame = f;
}
@Override
public Flow exe(Frame cf) {
Flow fl = code.exe(cf);
if (!fl.isNormal()) {
return fl;
}
Ex cd;
try {
cd = (Ex) fl.u();
} catch (Exception e) {
return Flow.thrw("ExCall no code: " + fl.u() + ": " + a2r("ExCall not code: ", e));
}
fl = frame.exe(cf);
if (!fl.isNormal()) {
return fl;
}
Frame fr;
try {
fr = (Frame) fl.u();
} catch (Exception e) {
return Flow.thrw("ExCall no frame: " + fl.u() + ": " + a2r("ExCall not frame: ", e));
}
fl = cd.exe(fr);
return fl.isReturn() ? Flow.normal(fl.u()) : fl;
}
}
class ExReturn extends Ex {
final Ex ret;
public ExReturn(Ex e1) {
ret = e1;
}
@Override
public Flow exe(Frame cf) {
Flow f = ret.exe(cf);
return f.isNormal() ? Flow.ret(f.u()) : f;
}
public void format(Formatter f) {
f.format(1, ret);
}
}
/*-------------------- throw and try ---------------------------------*/
class ExThrow extends Ex {
final Ex thrw;
public ExThrow(Ex e1) {
thrw = e1;
}
@Override
public Flow exe(Frame cf) {
Flow f = thrw.exe(cf);
return f.isNormal() ? Flow.thrw(f.u()) : f;
}
@Override
public void format(Formatter f) {
f.format(1, thrw);
}
}
class ExTry extends Ex {
final Ex eTry, eCatch, eHandle;
public ExTry(Ex t, Ex c, Ex h) {
eTry = t;
eCatch = c;
eHandle = h;
}
@Override
public Flow exe(Frame cf) {
Flow t = eTry.exe(cf);
if (!t.isThrow()) {
return t;
}
Flow c = eCatch.exe(cf);
if (!c.isNormal()) {
return c;
}
cf.put(c.u(), t.u());
return eHandle.exe(cf);
}
}
/*-------------------- finally, the factory ---------------------------------*/
public class ExFactory {
final static ExCF cf0 = new ExCF();
final static ExNF nf0 = new ExNF();
final static ExNew new0 = new ExNew();
final static Flow constNull = Flow.normal(null);
final Map<Object, JFun> jFunMap = new HashMap<Object, JFun>();
public Ex cf() {
return cf0;
}
public ExConst cnst(Object u) {
return new ExConst(Flow.normal(u));
}
public void jFunAdd(String key, JFun j) {
if (AbstractCompiler.resWords.matcher(key).matches()) {
err("jFunAdd illegal name " + key);
}
if (j.name == null) {
j.name = key;
} else {
err("jFunAdd but already registered: " + j.name + " key " + key);
}
jFunMap.put(key, j);
}
public boolean jFunExists(Object key) {
return jFunMap.get(key) != null;
}
public Ex jFun(Object key, Ex... e) {
JFun jf = jFunMap.get(key);
if (jf == null) {
if (key instanceof JFun) {
jf = (JFun) key;
} else {
err("syntax jFun no JFun at key=" + key);
}
}
return new ExJFun(jf, e);
}
/*
public Flow jFun(Flow f, ExJFunDyn j) {
return f.isNormal() ? Flow.normal(jFun(f.u(), Arrays.copyOfRange(j.exs, 1, j.exs.length))) : f;
}
public ExJFunDyn jFunDyn(Ex... e) {
return new ExJFunDyn(this, e);
}
public ExJFunDyn jFunDyn(Map<Object, Object> m) {
ArrayList<Ex> exs = new ArrayList<Ex>();
exs.add((Ex)m.get("fun"));
for(int ix=1; ; ix++) {
if (m.containsKey(ix))
exs.add((Ex)m.get(ix));
else
return jFunDyn(exs.toArray(new Ex[exs.size()]));
}
}
*/
public Ex exNew() {
return new0;
}
public Ex nf() {
return nf0;
}
public ExGet get(Ex map, Ex key) {
return new ExGet(map, key);
}
public ExAss ass(Ex map, Ex key, Ex val) {
return new ExAss(map, key, val);
}
public Ex exFor(Ex eFor, Ex eIn, Ex eDo) {
return new ExFor(eFor, eIn, eDo);
}
public Ex exIf(Ex i, Ex t, Ex e) {
return new ExIf(i, t, e);
}
public ExSeq seq(Ex... exs) {
if (exs.length == 0) {
out("???exs empty");
} else if (exs[0] == null) {
out("???ex[0] null");
}
return new ExSeq(exs);
}
public Ex whl(Ex cond, Ex st) {
return new ExWhile(cond, st);
}
/* public Ex fun(Ex e) {
return new ExFun(e);
}
*/
public Ex call(Ex code, Ex frame) {
return new ExCall(code, frame);
}
/*
public Ex det(Ex e) {
return new ExDet(e);
}
public Ex exExe(Ex e) {
return new ExCall(e, null);
}
*/
public Ex ret(Ex e) {
return new ExReturn(e);
}
public Ex ret(Object o) {
return new ExReturn(cnst(o));
}
public Ex thrw(Ex e) {
return new ExThrow(e);
}
public Ex thrw(Object o) {
return new ExThrow(cnst(o));
}
public Ex exTry(Ex eTry, Ex eCatch, Ex eHandle) {
return new ExTry(eTry, eCatch, eHandle);
}
public Ex ex(String name, Ex... exs) {
if (exs == null || exs.length == 0) {
if ("cf".equals(name)) {
return cf();
}
if ("new".equals(name)) {
return exNew();
}
} else if (exs.length == 1) {
if ("return".equals(name)) {
return ret(exs[0]);
}
if ("throw".equals(name)) {
return thrw(exs[0]);
}
} else if (exs.length == 2) {
if ("call".equals(name)) {
return call(exs[0], exs[1]);
}
if ("get".equals(name)) {
return get(exs[0], exs[1]);
}
if ("while".equals(name)) {
return whl(exs[0], exs[1]);
}
} else if (exs.length == 3) {
if ("ass".equals(name)) {
return ass(exs[0], exs[1], exs[2]);
}
if ("for".equals(name)) {
return exFor(exs[0], exs[1], exs[2]);
}
if ("if".equals(name)) {
return exIf(exs[0], exs[1], exs[2]);
}
if ("try".equals(name)) {
return exTry(exs[0], exs[1], exs[2]);
}
}
if ("seq".equals(name)) {
return seq(exs);
}
err("no Ex named " + name + " with " + (exs == null ? "null" : exs.length) + " operands");
return null;
}
}