abstract sclass CtxExpr { // assumes that ctxContext() is set abstract bool get(); abstract S str(); } abstract sclass CtxGeneral extends CtxExpr { bool get() { ret eqic(str(), "true"); } } abstract sclass CtxBool extends CtxExpr { S str() { ret get() ? "true" : "false"; } } sclass CtxConst extends CtxGeneral { S value; *() {} *(S *value) {} // assume it's a regexp when queried with get() // and a string constant when queried with str() // (maybe we don't need this trick anymore) S str() { ret value; } bool get() { ret ctxEvalPattern(value); } } sclass CtxVar extends CtxGeneral { S var; *() {} *(S *var) {} S str() { ret ctxGetVar(var); } } sclass CtxNeg extends CtxBool { CtxExpr e; *() {} *(CtxExpr *e) {} bool get() { ret !e.get(); } } sclass CtxAnd extends CtxBool { CtxExpr a, b; *() {} *(CtxExpr *a, CtxExpr *b) {} bool get() { ret a.get() && b.get(); } } sclass CtxOr extends CtxBool { CtxExpr a, b; *() {} *(CtxExpr *a, CtxExpr *b) {} bool get() { ret a.get() || b.get(); } } sclass CtxRegexp extends CtxBool { S pattern; *() {} *(S *pattern) {} bool get() { ret ctxEvalPattern(pattern); } } sclass CtxComp extends CtxBool { CtxExpr a, b; *() {} *(CtxExpr *a, CtxExpr *b) {} bool get() { ret eq(a.str(), b.str()); } } sclass CtxUneq extends CtxBool { CtxExpr a, b; *() {} *(CtxExpr *a, CtxExpr *b) {} bool get() { ret neq(a.str(), b.str()); } } sclass CtxMatch extends CtxBool { CtxExpr var; S pattern; *() {} *(CtxExpr *var, S *pattern) {} bool get() { ret ctxEvalPattern(pattern, var.str()); } } sclass CtxFCall extends CtxGeneral { S fname; new L args; *() {} *(S *fname) {} void add(CtxExpr arg) { args.add(arg); } S str() { ret ctxCallFunction(fname, map(func(CtxExpr e) -> S { e.str() }, args)); } }