public override STModel Convert(iterexpr ie, Symtab stab) { var solver = stb.Solver; int binderid = stab.Get(ie.binder).id; List <int> bekVarIds = new List <int>(); List <Expr> bekVarVals = new List <Expr>(); List <Sort> bekVarSorts = new List <Sort>(); Dictionary <int, int> proj = new Dictionary <int, int>(); foreach (iterassgn ia in IterInfo.Initializers(ie, stab)) { proj[stab.Get(ia.lhs).id] = bekVarIds.Count; bekVarIds.Add(stab.Get(ia.lhs).id); bekVarVals.Add(MkExpr(stab.Get(ia.lhs).type, ia.rhs)); bekVarSorts.Add(BekTypeToSort(stab.Get(ia.lhs).type)); } int K = bekVarSorts.Count; //register sort Sort regSort = (K == 0 ? solver.UnitSort : (K == 1 ? bekVarSorts[0] : solver.MkTupleSort(bekVarSorts.ToArray()))); //initial register value Expr initReg = (K == 0 ? solver.UnitConst : (K == 1 ? bekVarVals[0] : solver.MkTuple(bekVarVals.ToArray()))); //input character variable Expr c = this.stb.MkInputVariable(charsort); //register variable Expr r = this.stb.MkRegister(regSort); //maps variable identifiers used in the bek program to corresponding term variables Dictionary <int, Expr> varMap = new Dictionary <int, Expr>(); varMap[binderid] = c; for (int i = 0; i < K; i++) { varMap[bekVarIds[i]] = (K == 1 ? r : solver.MkProj(i, r)); } List <Move <Rulez3> > moves = new List <Move <Rulez3> >(); Expr previousCaseNegated = solver.True; foreach (itercase curcase in ie.GetNormalCases()) { if (!solver.IsSatisfiable(previousCaseNegated)) { break; } //initial symbolic values are the previous register values Expr[] regs0 = new Expr[K]; for (int i = 0; i < K; i++) { regs0[i] = varMap[bekVarIds[i]]; } Expr[] regs = new Expr[K]; for (int i = 0; i < K; i++) { regs[i] = regs0[i]; } //gets the current symbolic value of ident Func <ident, Expr> idents = x => { SymtabElt se = stab.Get(x); if (se.id == binderid) { return(c); //the input character } return(regs0[proj[se.id]]); //the current sybolic value of x }; //current condition is the case condition and not the previous case conditions Expr casecond = this.expr_handler.Convert(curcase.cond, idents); Expr guard = stb.And(previousCaseNegated, casecond); Expr not_casecond = stb.Not(casecond); previousCaseNegated = stb.And(previousCaseNegated, solver.MkNot(casecond)); List <Expr> yields = new List <Expr>(); if (solver.IsSatisfiable(guard)) { #region iterate over the iter statements in the body foreach (iterstmt ist in curcase.body) { //gets the current symbolic value of ident //note that the symbolic value may have been updated by a previous assignment Func <ident, Expr> idents1 = x => { SymtabElt se = stab.Get(x); if (se.id == binderid) { return(c); //the input character } return(regs0[proj[se.id]]); //the current sybolic value of x }; iterassgn a = ist as iterassgn; if (a != null) { var v = expr_handler.Convert(a.rhs, idents1); regs[proj[stab.Get(a.lhs).id]] = v; } else { yieldstmt y = ist as yieldstmt; if (y != null) { foreach (var e in y.args) { strconst s = e as strconst; if (s == null) { yields.Add(expr_handler.Convert(e, idents1)); } else { foreach (int sc in s.content) { yields.Add(solver.MkNumeral(sc, charsort)); } } } } else { throw new BekException(); //TBD: undefined case } } } #endregion Expr upd = (K == 0 ? solver.UnitConst : (K == 1 ? regs[0] : solver.MkTuple(regs))); moves.Add(stb.MkRule(0, 0, guard, upd, yields.ToArray())); } } previousCaseNegated = solver.True; bool noEndCases = true; foreach (itercase curcase in ie.GetEndCases()) { noEndCases = false; if (!solver.IsSatisfiable(previousCaseNegated)) { break; } //initial symbolic values are the previous register values Expr[] regs = new Expr[K]; for (int i = 0; i < K; i++) { regs[i] = varMap[bekVarIds[i]]; } //gets the current symbolic value of ident Func <ident, Expr> idents = x => { SymtabElt se = stab.Get(x); if (se.id == binderid) { throw new BekException("Input var must not occur in an end case"); } return(regs[proj[se.id]]); //the current sybolic value of x }; //current condition is the case condition and not the previous case conditions Expr casecond = this.expr_handler.Convert(curcase.cond, idents); Expr guard = stb.And(previousCaseNegated, casecond); Expr not_casecond = stb.Not(casecond); previousCaseNegated = stb.And(previousCaseNegated, solver.MkNot(casecond)); List <Expr> yields = new List <Expr>(); if (solver.IsSatisfiable(guard)) { #region iterate over the iter statements in the body foreach (iterstmt ist in curcase.body) { //gets the current symbolic value of ident //note that the symbolic value may have been updated by a previous assignment Func <ident, Expr> idents1 = x => { SymtabElt se = stab.Get(x); if (se.id == binderid) { throw new BekException("Input var must not occur in an end case"); } return(regs[proj[se.id]]); //the current sybolic value of x }; iterassgn a = ist as iterassgn; if (a != null) { var v = expr_handler.Convert(a.rhs, idents1); regs[proj[stab.Get(a.lhs).id]] = v; } else { yieldstmt y = ist as yieldstmt; if (y != null) { foreach (var e in y.args) { strconst s = e as strconst; if (s == null) { yields.Add(expr_handler.Convert(e, idents1)); } else { foreach (int sc in s.content) { yields.Add(solver.MkNumeral(sc, charsort)); } } } } else { throw new BekException(); //TBD: undefined case } } } #endregion moves.Add(stb.MkFinalOutput(0, guard, yields.ToArray())); } } //if no end cases were given, assume default true end case with empty yield if (noEndCases) { moves.Add(stb.MkFinalOutput(0, solver.True)); } STModel iterST = STModel.Create(solver, "iter", initReg, charsort, charsort, regSort, 0, moves); iterST.Simplify(); return(iterST); }
private BranchingRule <Expr> CreateBodyRule(List <iterstmt> iters, Expr pathCond, VarInfo I) { if (iters.Count == 0) { return(new UndefRule <Expr>()); } //iterate over the iters to create a single register update Expr[] regs = new Expr[I.K]; for (int i = 0; i < I.K; i++) { regs[i] = I.GetRegExpr_i(i); } //sequential semantics //Func<ident, Expr> idmap = (i => (I.binderid.Equals(I.GetBekVarNr(i)) ? I.c : (regs[I.GetRegNr(i)]))); Func <ident, Expr> idmap = I.GetVarExpr; //parallel semantics List <Expr> yields = new List <Expr>(); raisestmt raise = null; ifthenelse ite = null; foreach (var ist in iters) { iterassgn a = ist as iterassgn; if (a != null) { var v = expr_handler.Convert(a.rhs, idmap); regs[I.GetRegNr(a.lhs)] = v; } else if (ist is yieldstmt) { yieldstmt y = ist as yieldstmt; foreach (var e in y.args) { strconst s = e as strconst; if (s == null) { yields.Add(expr_handler.Convert(e, idmap)); } else { foreach (int sc in s.content) { yields.Add(stb.Solver.MkNumeral(sc, charsort)); } } } } else if (ist is ifthenelse) { ite = (ifthenelse)ist; //we know that there can only be a single ite break; // } else { raise = (raisestmt)ist; break; // } } if (raise != null) { var rule = new UndefRule <Expr>(raise.exc); return(rule); } else if (ite != null) { var branchCond = expr_handler.Convert(ite.cond, I.GetVarExpr); //check feasability of the true and false branches, eliminate dead code var pathCond_and_branchCond = stb.And(pathCond, branchCond); var pathCond_and_not_branchCond = stb.And(pathCond, stb.Not(branchCond)); if (!stb.Solver.IsSatisfiable(pathCond_and_branchCond)) { //the path condition implies the negated branch condition return(CreateBodyRule(ite.fcase, pathCond, I)); } else if (!stb.Solver.IsSatisfiable(pathCond_and_not_branchCond)) { //the path condition implies the branch condition return(CreateBodyRule(ite.tcase, pathCond, I)); } else { var tCase = CreateBodyRule(ite.tcase, pathCond_and_branchCond, I); var fCase = CreateBodyRule(ite.fcase, pathCond_and_not_branchCond, I); var iterule = new IteRule <Expr>(branchCond, tCase, fCase); return(iterule); } } else { Expr regExpr = (regs.Length == 1 ? regs[0] : stb.Solver.MkTuple(regs)); var rule = new BaseRule <Expr>(new Sequence <Expr>(yields.ToArray()), regExpr, 0); return(rule); } }