public void TestIntZ3() { var solver = new Z3Provider(); var isNeg = solver.MkLt(solver.MkVar(0, solver.IntSort), solver.MkInt(0)); var isPos = solver.MkLt(solver.MkInt(0), solver.MkVar(0, solver.IntSort)); var sort = solver.CharacterSort; //if x has a negative label then x has successor y with a nonnegative label var x = new Variable("x", true); var y = new Variable("y", true); var psi = new MSOImplies <Expr>( new MSOPredicate <Expr>(isNeg, x), new MSOExists <Expr>(y, new MSOAnd <Expr>( new MSOSuccN <Expr>(x, y, 1), new MSOPredicate <Expr>(isPos, y) ) ) ); //all negative labels are immediately followed by a positive label MSOFormula <Expr> phi = new MSOForall <Expr>(x, psi); var ca = new CartesianAlgebraBDD <Expr>(solver); var aut_psi = psi.GetAutomaton(ca).Determinize().Minimize(); var aut_phi = phi.GetAutomaton(solver).Determinize().Minimize(); Assert.IsFalse(aut_phi.IsEmpty); //aut_phi.ShowGraph("aut_phi"); //aut_psi.ShowGraph("aut_psi"); }
private Variable ConvertSet(MonaExpr set, MapStack <string, MonaParam> locals, out MSOFormula <BDD> psi) { if (set.NrOfSubexprs == 0) { return(ConvertEmptyset(out psi)); } MSOFormula <BDD> disj = null; Variable x = MkNewVar1(); Variable X = MkNewVar2(); for (int i = 0; i < set.NrOfSubexprs; i++) { MonaExpr t = set[i]; if (t.symbol.Kind == Tokens.RANGE) { MSOFormula <BDD> from_psi; Variable from = ConvertTerm1(t[0], locals, out from_psi); MSOFormula <BDD> to_psi; Variable to = ConvertTerm1(t[1], locals, out to_psi); MSOFormula <BDD> range = AddConstraints(from_psi, from, to_psi, to, new MSOAnd <BDD>(new MSOLe <BDD>(from, x), new MSOLe <BDD>(x, to))); if (disj == null) { disj = range; } else { disj = new MSOOr <BDD>(disj, range); } } else { MSOFormula <BDD> y_psi; Variable y = ConvertTerm1(t, locals, out y_psi); MSOFormula <BDD> elem = new MSOEq <BDD>(x, y); if (y_psi != null) { elem = new MSOExists <BDD>(y, new MSOAnd <BDD>(y_psi, elem)); } if (disj == null) { disj = elem; } else { disj = new MSOOr <BDD>(disj, elem); } } } var pred = new MSOForall <BDD>(x, new MSOEquiv <BDD>(new MSOIn <BDD>(x, X), disj)); psi = pred; return(X); }
Automaton<T> CreateAutomaton3<T>(Func<int, T> f, int bitWidth, IBooleanAlgebra<T> Z) { Func<int, Variable, MSOPredicate<T>> pred = (i, s) => new MSOPredicate<T>(f(i), s); MSOFormula<T> phi = new MSOTrue<T>(); // x1<x2<x3<x4... for (int index = 1; index < bitWidth; index++) { MSOFormula<T> phi1 = new MSOLt<T>(V1("x" + (index - 1)), V1("x" + index)); phi = new MSOAnd<T>(phi, phi1); } // bi(xi) for (int index = 0; index < bitWidth; index++) { MSOFormula<T> phi1 = pred(index, V1("x" + index)); phi = new MSOAnd<T>(phi, phi1); } // exists forall... for (int index = 0; index < bitWidth; index++) { if (index % 2 == 0) phi = new MSOExists<T>(V1("x" + index), phi); else phi = new MSOForall<T>(V1("x" + index), phi); } var aut = phi.GetAutomaton(Z); return aut; }
public void TestMSO_Succ() { var solver = new CharSetSolver(BitWidth.BV32); var x = new Variable("x", true); var y = new Variable("y", true); MSOFormula <BDD> phi = new MSOForall <BDD>(x, new MSOImplies <BDD>( new MSOPredicate <BDD>(solver.MkCharConstraint('c'), x), new MSOExists <BDD>(y, new MSOAnd <BDD>( new MSOSuccN <BDD>(x, y, 1), new MSOPredicate <BDD>(solver.MkCharConstraint('a'), y) ) ) ) ); var aut = phi.GetAutomaton(solver); for (int i = 0; i < 10; i++) { var s = solver.GenerateMember(aut); Assert.IsTrue(System.Text.RegularExpressions.Regex.IsMatch(s, "^(ca|[^c])*$")); } var aut2 = solver.RegexConverter.Convert("^(ca|[^c])*$"); Assert.IsTrue(aut2.IsEquivalentWith(aut)); }
public void TestWS1S_Forall_x_Exists_y_x_lt_y() { var triv = new TrivialBooleanAlgebra(); var ca = new BDDAlgebra<bool>(triv); var x = new Variable("x", true); var y = new Variable("y", true); var x_lt_y = new MSOLt<bool>(x, y); var aut_x_lt_y = x_lt_y.GetAutomaton(ca); //aut_x_lt_y.ShowGraph("aut_x_lt_y"); var psi4 = new MSOForall<bool>(x, new MSOExists<bool>(y, (x_lt_y))); var aut = psi4.GetAutomaton(ca); //accepts only the empty word Assert.IsTrue(aut.StateCount == 1 && aut.IsFinalState(aut.InitialState) && aut.MoveCount == 0); }
public void TestMSO_Forall() { var solver = new CharSetSolver(BitWidth.BV16); var x = new Variable("x", true); MSOFormula<BDD> phi = new MSOForall<BDD>(x, new MSOPredicate<BDD>(solver.MkCharConstraint('c',true), x)); var aut = phi.GetAutomaton(solver); //aut.ShowGraph("aut"); for (int i = 0; i < 10; i++) { TestContext.WriteLine(solver.GenerateMember(aut)); } var aut2 = solver.RegexConverter.Convert("^(c|C)*$"); //aut2.ShowGraph("aut2"); Assert.IsTrue(aut2.IsEquivalentWith(aut)); }
private Variable ConvertSetminus(MonaExpr set1, MonaExpr set2, MapStack <string, MonaParam> locals, out MSOFormula <BDD> pred) { MSOFormula <BDD> psi1; var X1 = ConvertTerm2(set1, locals, out psi1); MSOFormula <BDD> psi2; var X2 = ConvertTerm2(set2, locals, out psi2); var X = MkNewVar2(); var x = MkNewVar1(); MSOFormula <BDD> diff = new MSOForall <BDD>(x, new MSOEquiv <BDD>(new MSOIn <BDD>(x, X), new MSOAnd <BDD>(new MSOIn <BDD>(x, X1), new MSONot <BDD>(new MSOIn <BDD>(x, X2))))); pred = AddConstraints(psi2, X2, psi1, X1, diff); return(X); }
public void TestMSO_Or() { var solver = new CharSetSolver(BitWidth.BV32); MSOFormula<BDD> phi = new MSOForall<BDD>(V1("x"), new MSOOr<BDD>( new MSOPredicate<BDD>(solver.MkCharConstraint( 'c'), V1("x")), new MSOPredicate<BDD>(solver.MkCharConstraint( 'a'), V1("x")) ) ); var aut = phi.GetAutomaton(solver); for (int i = 0; i < 10; i++) { var s = solver.GenerateMember(aut); Assert.IsTrue(System.Text.RegularExpressions.Regex.IsMatch(s, "^[ac]*$")); } var aut2 = solver.RegexConverter.Convert("^[ac]*$"); Assert.IsTrue(aut2.IsEquivalentWith(aut)); }
static Automaton <T> CreateAutomaton3 <T>(Func <int, T> f, int bitWidth, IBooleanAlgebra <T> Z) { Func <int, string, MSOPredicate <T> > pred = (i, s) => new MSOPredicate <T>(f(i), new Variable(s, true)); MSOFormula <T> phi = new MSOTrue <T>(); // x1<x2<x3<x4... for (int index = 1; index < bitWidth; index++) { MSOFormula <T> phi1 = new MSOLt <T>(new Variable("x" + (index - 1), true), new Variable("x" + index, true)); phi = new MSOAnd <T>(phi, phi1); } // bi(xi) for (int index = 0; index < bitWidth; index++) { MSOFormula <T> phi1 = pred(index, "x" + index); phi = new MSOAnd <T>(phi, phi1); } // exists forall... for (int index = 0; index < bitWidth; index++) { if (index % 2 == 0) { phi = new MSOExists <T>(new Variable("x" + index, true), phi); } else { phi = new MSOForall <T>(new Variable("x" + index, true), phi); } } var aut = phi.GetAutomaton(Z); return(aut); }
private MSOFormula <BDD> ConvertFormula(MonaExpr expr, MapStack <string, MonaParam> locals) { switch (expr.symbol.Kind) { case Tokens.TRUE: return(new MSOTrue <BDD>()); case Tokens.FALSE: return(new MSOFalse <BDD>()); case Tokens.NOT: return(new MSONot <BDD>(ConvertFormula(expr[0], locals))); case Tokens.AND: return(new MSOAnd <BDD>(ConvertFormula(expr[0], locals), ConvertFormula(expr[1], locals))); case Tokens.OR: return(new MSOOr <BDD>(ConvertFormula(expr[0], locals), ConvertFormula(expr[1], locals))); case Tokens.IMPLIES: return(new MSOImplies <BDD>(ConvertFormula(expr[0], locals), ConvertFormula(expr[1], locals))); case Tokens.EQUIV: return(new MSOEquiv <BDD>(ConvertFormula(expr[0], locals), ConvertFormula(expr[1], locals))); case Tokens.EQ: return(ConvertEq(expr[0], expr[1], locals)); case Tokens.NE: return(new MSONot <BDD>(ConvertEq(expr[0], expr[1], locals))); case Tokens.LT: return(ConvertLt(expr[0], expr[1], locals)); case Tokens.GT: return(ConvertLt(expr[1], expr[0], locals)); case Tokens.LE: return(ConvertLe(expr[0], expr[1], locals)); case Tokens.GE: return(ConvertLe(expr[1], expr[0], locals)); case Tokens.SUBSET: return(ConvertSubset(expr[1], expr[0], locals)); case Tokens.IN: return(ConvertIn(expr[0], expr[1], locals)); case Tokens.NOTIN: return(new MSONot <BDD>(ConvertIn(expr[0], expr[1], locals))); case Tokens.EMPTY: return(ConvertIsEmpty(expr[0], locals)); case Tokens.EX1: case Tokens.EX2: { MonaQFormula phi = (MonaQFormula)expr; if ((phi.universes != null && phi.universes.Count > 1) || phi.vars.Exists(vw => vw.where != null)) { throw new NotImplementedException(expr.ToString()); } MSOFormula <BDD> psi = ConvertFormula(phi.formula, locals.Push(phi.varmap)); foreach (var vw in phi.vars) { psi = new MSOExists <BDD>(new Variable(vw.name, phi.varmap[vw.name].type == MonaExprType.INT), psi); } return(psi); } case Tokens.ALL1: case Tokens.ALL2: { MonaQFormula phi = (MonaQFormula)expr; if ((phi.universes != null && phi.universes.Count > 1) || phi.vars.Exists(vw => vw.where != null)) { throw new NotImplementedException(expr.ToString()); } MSOFormula <BDD> psi = ConvertFormula(phi.formula, locals.Push(phi.varmap)); foreach (var vw in phi.vars) { psi = new MSOForall <BDD>(new Variable(vw.name, phi.varmap[vw.name].type == MonaExprType.INT), psi); } return(psi); } default: throw new NotImplementedException(expr.ToString()); } }
private static Pair<MSOFormula<BoolExpr>, List<BoolExpr>> GenerateMSOFormula(int maxVarIndex) { int randomNumber = random.Next(0, 8); size--; if (size <= 0) { int variable = random.Next(0, maxVarIndex-1); BoolExpr b = GeneratePredicateOut(200); List<BoolExpr> l = new List<BoolExpr>(); l.Add(b); return new Pair<MSOFormula<BoolExpr>, List<BoolExpr>>(new MSOPredicate<BoolExpr>(b, new Variable("x"+variable, true)), l); } switch (randomNumber) { case 0: { Pair<MSOFormula<BoolExpr>, List<BoolExpr>> phi1 = GenerateMSOFormula(maxVarIndex + 1); MSOFormula<BoolExpr> phi = new MSOExists<BoolExpr>(new Variable("x"+maxVarIndex, true), phi1.First); return new Pair<MSOFormula<BoolExpr>, List<BoolExpr>>(phi, phi1.Second); } case 1: { Pair<MSOFormula<BoolExpr>, List<BoolExpr>> phi1 = GenerateMSOFormula(maxVarIndex + 1); MSOFormula<BoolExpr> phi = new MSOForall<BoolExpr>(new Variable("x" + maxVarIndex, true), phi1.First); return new Pair<MSOFormula<BoolExpr>, List<BoolExpr>>(phi, phi1.Second); } case 2: case 3: { Pair<MSOFormula<BoolExpr>, List<BoolExpr>> phi1 = GenerateMSOFormula(maxVarIndex); Pair<MSOFormula<BoolExpr>, List<BoolExpr>> phi2 = GenerateMSOFormula(maxVarIndex); MSOFormula<BoolExpr> phi = new MSOAnd<BoolExpr>(phi1.First, phi2.First); return new Pair<MSOFormula<BoolExpr>, List<BoolExpr>>(phi, new List<BoolExpr>(phi1.Second.Union(phi2.Second))); } case 4: case 5: { Pair<MSOFormula<BoolExpr>, List<BoolExpr>> phi1 = GenerateMSOFormula(maxVarIndex); Pair<MSOFormula<BoolExpr>, List<BoolExpr>> phi2 = GenerateMSOFormula(maxVarIndex); MSOFormula<BoolExpr> phi = new MSOOr<BoolExpr>(phi1.First, phi2.First); return new Pair<MSOFormula<BoolExpr>, List<BoolExpr>>(phi, new List<BoolExpr>(phi1.Second.Union(phi2.Second))); } case 6: { Pair<MSOFormula<BoolExpr>, List<BoolExpr>> phi1 = GenerateMSOFormula(maxVarIndex); MSOFormula<BoolExpr> phi = new MSONot<BoolExpr>(phi1.First); return new Pair<MSOFormula<BoolExpr>, List<BoolExpr>>(phi, phi1.Second); } case 7: { if (maxVarIndex > 1) { int variable1 = random.Next(0, maxVarIndex - 1); int variable2 = random.Next(0, maxVarIndex - 1); if (variable1 == variable2) { if (variable1 == maxVarIndex - 1) variable1 = variable1 - 1; else variable2 = variable2 + 1; } //Successor MSOFormula<BoolExpr> phi = new MSOSuccN<BoolExpr>(varOf(variable1),varOf(variable2),random.Next(1,4)); return new Pair<MSOFormula<BoolExpr>, List<BoolExpr>>(phi, new List<BoolExpr>()); } else { int variable = random.Next(0, maxVarIndex - 1); BoolExpr b = GeneratePredicate(); List<BoolExpr> l = new List<BoolExpr>(); l.Add(b); return new Pair<MSOFormula<BoolExpr>, List<BoolExpr>>(new MSOPredicate<BoolExpr>(b, new Variable("x" + variable, true)), l); } } case 8: { int variable1 = random.Next(0, maxVarIndex - 1); int variable2 = random.Next(0, maxVarIndex - 1); //less than MSOFormula<BoolExpr> phi = new MSOLe<BoolExpr>(varOf(variable1), varOf(variable2)); return new Pair<MSOFormula<BoolExpr>, List<BoolExpr>>(phi, new List<BoolExpr>()); } } return null; }
private static Pair <MSOFormula <BoolExpr>, List <BoolExpr> > GenerateMSOFormula(int maxVarIndex) { int randomNumber = random.Next(0, 8); size--; if (size <= 0) { int variable = random.Next(0, maxVarIndex - 1); BoolExpr b = GeneratePredicateOut(200); List <BoolExpr> l = new List <BoolExpr>(); l.Add(b); return(new Pair <MSOFormula <BoolExpr>, List <BoolExpr> >(new MSOPredicate <BoolExpr>(b, new Variable("x" + variable, true)), l)); } switch (randomNumber) { case 0: { Pair <MSOFormula <BoolExpr>, List <BoolExpr> > phi1 = GenerateMSOFormula(maxVarIndex + 1); MSOFormula <BoolExpr> phi = new MSOExists <BoolExpr>(new Variable("x" + maxVarIndex, true), phi1.First); return(new Pair <MSOFormula <BoolExpr>, List <BoolExpr> >(phi, phi1.Second)); } case 1: { Pair <MSOFormula <BoolExpr>, List <BoolExpr> > phi1 = GenerateMSOFormula(maxVarIndex + 1); MSOFormula <BoolExpr> phi = new MSOForall <BoolExpr>(new Variable("x" + maxVarIndex, true), phi1.First); return(new Pair <MSOFormula <BoolExpr>, List <BoolExpr> >(phi, phi1.Second)); } case 2: case 3: { Pair <MSOFormula <BoolExpr>, List <BoolExpr> > phi1 = GenerateMSOFormula(maxVarIndex); Pair <MSOFormula <BoolExpr>, List <BoolExpr> > phi2 = GenerateMSOFormula(maxVarIndex); MSOFormula <BoolExpr> phi = new MSOAnd <BoolExpr>(phi1.First, phi2.First); return(new Pair <MSOFormula <BoolExpr>, List <BoolExpr> >(phi, new List <BoolExpr>(phi1.Second.Union(phi2.Second)))); } case 4: case 5: { Pair <MSOFormula <BoolExpr>, List <BoolExpr> > phi1 = GenerateMSOFormula(maxVarIndex); Pair <MSOFormula <BoolExpr>, List <BoolExpr> > phi2 = GenerateMSOFormula(maxVarIndex); MSOFormula <BoolExpr> phi = new MSOOr <BoolExpr>(phi1.First, phi2.First); return(new Pair <MSOFormula <BoolExpr>, List <BoolExpr> >(phi, new List <BoolExpr>(phi1.Second.Union(phi2.Second)))); } case 6: { Pair <MSOFormula <BoolExpr>, List <BoolExpr> > phi1 = GenerateMSOFormula(maxVarIndex); MSOFormula <BoolExpr> phi = new MSONot <BoolExpr>(phi1.First); return(new Pair <MSOFormula <BoolExpr>, List <BoolExpr> >(phi, phi1.Second)); } case 7: { if (maxVarIndex > 1) { int variable1 = random.Next(0, maxVarIndex - 1); int variable2 = random.Next(0, maxVarIndex - 1); if (variable1 == variable2) { if (variable1 == maxVarIndex - 1) { variable1 = variable1 - 1; } else { variable2 = variable2 + 1; } } //Successor MSOFormula <BoolExpr> phi = new MSOSuccN <BoolExpr>(varOf(variable1), varOf(variable2), random.Next(1, 4)); return(new Pair <MSOFormula <BoolExpr>, List <BoolExpr> >(phi, new List <BoolExpr>())); } else { int variable = random.Next(0, maxVarIndex - 1); BoolExpr b = GeneratePredicate(); List <BoolExpr> l = new List <BoolExpr>(); l.Add(b); return(new Pair <MSOFormula <BoolExpr>, List <BoolExpr> >(new MSOPredicate <BoolExpr>(b, new Variable("x" + variable, true)), l)); } } case 8: { int variable1 = random.Next(0, maxVarIndex - 1); int variable2 = random.Next(0, maxVarIndex - 1); //less than MSOFormula <BoolExpr> phi = new MSOLe <BoolExpr>(varOf(variable1), varOf(variable2)); return(new Pair <MSOFormula <BoolExpr>, List <BoolExpr> >(phi, new List <BoolExpr>())); } } return(null); }
private Variable ConvertUnion(MonaExpr set1, MonaExpr set2, MapStack<string, MonaParam> locals, out MSOFormula<BDD> pred) { MSOFormula<BDD> psi1; var X1 = ConvertTerm2(set1, locals, out psi1); MSOFormula<BDD> psi2; var X2 = ConvertTerm2(set2, locals, out psi2); var X = MkNewVar2(); var x = MkNewVar1(); MSOFormula<BDD> union = new MSOForall<BDD>(x, new MSOEquiv<BDD>(new MSOIn<BDD>(x, X), new MSOOr<BDD>(new MSOIn<BDD>(x, X1), new MSOIn<BDD>(x, X2)))); pred = AddConstraints(psi2, X2, psi1, X1, union); return X; }
private Variable ConvertSet(MonaExpr set, MapStack<string, MonaParam> locals, out MSOFormula<BDD> psi) { if (set.NrOfSubexprs == 0) return ConvertEmptyset(out psi); MSOFormula<BDD> disj = null; Variable x = MkNewVar1(); Variable X = MkNewVar2(); for (int i=0; i < set.NrOfSubexprs; i++) { MonaExpr t = set[i]; if (t.symbol.Kind == Tokens.RANGE) { MSOFormula<BDD> from_psi; Variable from = ConvertTerm1(t[0], locals, out from_psi); MSOFormula<BDD> to_psi; Variable to = ConvertTerm1(t[1], locals, out to_psi); MSOFormula<BDD> range = AddConstraints(from_psi, from, to_psi, to, new MSOAnd<BDD>(new MSOLe<BDD>(from, x), new MSOLe<BDD>(x, to))); if (disj == null) disj = range; else disj = new MSOOr<BDD>(disj, range); } else { MSOFormula<BDD> y_psi; Variable y = ConvertTerm1(t, locals, out y_psi); MSOFormula<BDD> elem = new MSOEq<BDD>(x, y); if (y_psi != null) elem = new MSOExists<BDD>(y, new MSOAnd<BDD>(y_psi, elem)); if (disj == null) disj = elem; else disj = new MSOOr<BDD>(disj, elem); } } var pred = new MSOForall<BDD>(x, new MSOEquiv<BDD>(new MSOIn<BDD>(x, X), disj)); psi = pred; return X; }
private MSOFormula<BDD> ConvertFormula(MonaExpr expr, MapStack<string,MonaParam> locals) { switch (expr.symbol.Kind) { case Tokens.TRUE: return new MSOTrue<BDD>(); case Tokens.FALSE: return new MSOFalse<BDD>(); case Tokens.NOT: return new MSONot<BDD>(ConvertFormula(expr[0], locals)); case Tokens.AND: return new MSOAnd<BDD>(ConvertFormula(expr[0], locals), ConvertFormula(expr[1], locals)); case Tokens.OR: return new MSOOr<BDD>(ConvertFormula(expr[0], locals), ConvertFormula(expr[1], locals)); case Tokens.IMPLIES: return new MSOImplies<BDD>(ConvertFormula(expr[0], locals), ConvertFormula(expr[1], locals)); case Tokens.EQUIV: return new MSOEquiv<BDD>(ConvertFormula(expr[0], locals), ConvertFormula(expr[1], locals)); case Tokens.EQ: return ConvertEq(expr[0], expr[1], locals); case Tokens.NE: return new MSONot<BDD>(ConvertEq(expr[0], expr[1], locals)); case Tokens.LT: return ConvertLt(expr[0], expr[1], locals); case Tokens.GT: return ConvertLt(expr[1], expr[0], locals); case Tokens.LE: return ConvertLe(expr[0], expr[1], locals); case Tokens.GE: return ConvertLe(expr[1], expr[0], locals); case Tokens.SUBSET: return ConvertSubset(expr[1], expr[0], locals); case Tokens.IN: return ConvertIn(expr[0], expr[1], locals); case Tokens.NOTIN: return new MSONot<BDD>(ConvertIn(expr[0], expr[1], locals)); case Tokens.EMPTY: return ConvertIsEmpty(expr[0], locals); case Tokens.EX1: case Tokens.EX2: { MonaQFormula phi = (MonaQFormula)expr; if ((phi.universes != null && phi.universes.Count > 1) || phi.vars.Exists(vw => vw.where != null)) throw new NotImplementedException(expr.ToString()); MSOFormula<BDD> psi = ConvertFormula(phi.formula, locals.Push(phi.varmap)); foreach (var vw in phi.vars) psi = new MSOExists<BDD>(new Variable(vw.name, phi.varmap[vw.name].type == MonaExprType.INT), psi); return psi; } case Tokens.ALL1: case Tokens.ALL2: { MonaQFormula phi = (MonaQFormula)expr; if ((phi.universes != null && phi.universes.Count > 1) || phi.vars.Exists(vw => vw.where != null)) throw new NotImplementedException(expr.ToString()); MSOFormula<BDD> psi = ConvertFormula(phi.formula, locals.Push(phi.varmap)); foreach (var vw in phi.vars) psi = new MSOForall<BDD>(new Variable(vw.name, phi.varmap[vw.name].type == MonaExprType.INT), psi); return psi; } case Tokens.NAME: { var name = expr as MonaName; if (name != null) { //must be a nullary predicate application (var0 is not supported) var tmpPredApp = new MonaPredApp(name.symbol, Cons<MonaExpr>.Empty); return ConvertPredApp(tmpPredApp, locals); } var predApp = expr as MonaPredApp; if (predApp != null) { return ConvertPredApp(predApp, locals); } throw new NotImplementedException(expr.ToString()); } default: throw new NotImplementedException(expr.ToString()); } }