private static void WriteRuleNodes <T>(string source, STbRule <T> rule, System.IO.TextWriter tw, ISTb <T> stb, bool endcase) { UndefRule <T> raise = rule as UndefRule <T>; if (raise != null) { tw.WriteLine("{0} [fillcolor = {2}, label =\"{1}\"];", source, ShortenLabel(DisplayLabel(raise.Exc)), excColor); return; } BaseRule <T> block = rule as BaseRule <T>; if (block != null) { string lab = Describe(stb, block, endcase); if (endcase) { tw.WriteLine("{0} [fillcolor={1}, peripheries = 2, label =\"{2}\"];", source, accColor, DisplayLabel(lab)); } else { tw.WriteLine("{0} [label =\"{1}\"];", source, DisplayLabel(lab)); } return; } else { IteRule <T> ite = (IteRule <T>)rule; string lab = stb.PrettyPrint(ite.Condition); tw.WriteLine("{0} [label =\"{1}\", style=rounded];", source, ShortenLabel(DisplayLabel(lab))); WriteRuleNodes(source + "T", ite.TrueCase, tw, stb, endcase); WriteRuleNodes(source + "F", ite.FalseCase, tw, stb, endcase); } }
private static void WriteRuleLinks <T>(string cat, string prefix, BranchingRule <T> rule, System.IO.TextWriter tw, ISTb <T> stb, bool endcase, bool writegrouping) { //TBD: better visualization for switch rules rule = (rule is SwitchRule <T>?(rule as SwitchRule <T>).ToIteForVisualization() : rule); if (writegrouping) { tw.WriteLine("<Link Source=\"{0}\" Target=\"{1}\" Category=\"Contains\" />", cat, prefix); } if ((rule is UndefRule <T>) || (endcase && (rule is BaseRule <T>))) { return; //there are no further links } if (rule is BaseRule <T> ) { tw.WriteLine("<Link Source=\"{0}\" Target=\"{1}\" Category=\"RuleExit\" />", prefix, ((BaseRule <T>)rule).State); } else //if (rule is IteRule<T>) { IteRule <T> ite = (IteRule <T>)rule; tw.WriteLine("<Link Source=\"{0}\" Target=\"{1}\" Label=\"T\" Category=\"BranchCase\" />", prefix, prefix + "." + "T"); tw.WriteLine("<Link Source=\"{0}\" Target=\"{1}\" Label=\"F\" Category=\"BranchCase\" />", prefix, prefix + "." + "F"); WriteRuleLinks(cat, prefix + "." + "T", ite.TrueCase, tw, stb, endcase, writegrouping); WriteRuleLinks(cat, prefix + "." + "F", ite.FalseCase, tw, stb, endcase, writegrouping); } //else //switch rule //{ //} }
private static void WriteRuleNodes <T>(string prefix, BranchingRule <T> rule, System.IO.TextWriter tw, ISTb <T> stb, bool endcase) { BranchingRule <T> rule1 = (rule is SwitchRule <T>?(rule as SwitchRule <T>).ToIteForVisualization() : rule); UndefRule <T> raise = rule as UndefRule <T>; if (raise != null) { tw.WriteLine("<Node Id=\"{0}\" {1} Category=\"Reject\" />", prefix, DisplayLabel(raise.Exc)); return; } BaseRule <T> block = rule as BaseRule <T>; if (block != null) { string lab = Describe(stb, block, endcase); string cat = (endcase ? "Accept" : "BasicBlock"); tw.WriteLine("<Node Id=\"{0}\" {1} Category=\"{2}\" />", prefix, DisplayLabel(lab), cat); return; } else { IteRule <T> ite = (IteRule <T>)rule1; string lab = stb.PrettyPrint(ite.Condition); tw.WriteLine("<Node Id=\"{0}\" {1} Category=\"BranchCondition\" />", prefix, DisplayLabel(lab)); WriteRuleNodes(prefix + "." + "T", ite.TrueCase, tw, stb, endcase); WriteRuleNodes(prefix + "." + "F", ite.FalseCase, tw, stb, endcase); } }
private static void WriteRuleLinks <T>(string cat, string source, STbRule <T> rule, System.IO.TextWriter tw, ISTb <T> stb, bool endcase, bool writegrouping) { if ((rule is UndefRule <T>) || (endcase && (rule is BaseRule <T>))) { return; //there are no further links } if (rule is BaseRule <T> ) { tw.WriteLine("{0} -> s{1};", source, ((BaseRule <T>)rule).State); } else { IteRule <T> ite = (IteRule <T>)rule; tw.WriteLine("{0} -> {1} [label = \"T\"];", source, source + "T"); tw.WriteLine("{0} -> {1} [label = \"F\"];", source, source + "F"); WriteRuleLinks(cat, source + "T", ite.TrueCase, tw, stb, endcase, writegrouping); WriteRuleLinks(cat, source + "F", ite.FalseCase, tw, stb, endcase, writegrouping); } }
STb <FuncDecl, Expr, Sort> GenerateToBytes() { var ctx = _automataCtx.Z3; Expr inputVar = _automataCtx.MkVar(0, ctx.BoolSort); Expr registerVar = _automataCtx.MkVar(1, _automataCtx.MkTupleSort(ctx.MkBitVecSort(8), ctx.MkBitVecSort(32))); Sort outputSort = ctx.MkBitVecSort(8); Expr initialRegister = _automataCtx.MkTuple(ctx.MkBV(0, 8), ctx.MkBV(0, 32)); var stb = new STb <FuncDecl, Expr, Sort>(_automataCtx, DeclarationType.Name, inputVar.Sort, outputSort, registerVar.Sort, initialRegister, 0); BitVecExpr symbolProj = (BitVecExpr)_automataCtx.MkProj(0, registerVar); BitVecExpr counterProj = (BitVecExpr)_automataCtx.MkProj(1, registerVar); var withFalse = ctx.MkBVLSHR(symbolProj, ctx.MkBV(1, 8)); var withTrue = ctx.MkBVOR(withFalse, ctx.MkBV(0x80, 8)); var counterIncremented = ctx.MkBVAdd(counterProj, ctx.MkBV(1, 32)); var accumulateTrue = new BaseRule <Expr>(Sequence <Expr> .Empty, _automataCtx.MkTuple(withTrue, counterIncremented), 0); var accumulateFalse = new BaseRule <Expr>(Sequence <Expr> .Empty, _automataCtx.MkTuple(withFalse, counterIncremented), 0); var accumulate = new IteRule <Expr>(inputVar, accumulateTrue, accumulateFalse); var yieldTrueAndReset = new BaseRule <Expr>(new Sequence <Expr>(withTrue), initialRegister, 0); var yieldFalseAndReset = new BaseRule <Expr>(new Sequence <Expr>(withFalse), initialRegister, 0); var yieldAndReset = new IteRule <Expr>(inputVar, yieldTrueAndReset, yieldFalseAndReset); var move = new IteRule <Expr>(ctx.MkBVULT(counterProj, ctx.MkBV(7, 32)), accumulate, yieldAndReset); stb.AssignRule(0, move); STbRule <Expr> final = new BaseRule <Expr>(Sequence <Expr> .Empty, registerVar, 0); for (int i = 1; i <= 7; ++i) { var yieldRule = new BaseRule <Expr>(new Sequence <Expr>(ctx.MkBVLSHR(symbolProj, ctx.MkBV(8 - i, 8))), registerVar, 0); final = new IteRule <Expr>(ctx.MkEq(counterProj, ctx.MkBV(i, 32)), yieldRule, final); } stb.AssignFinalRule(0, final); return(stb); }
STModel ConvertReplace(replace repl) { //create a disjunction of all the regexes //each case terminated by the identifier int K = 0; //max pattern length //HashSet<int> finalReplacers = new HashSet<int>(); //for efficieny keep lookup tables of character predicates to sets Dictionary <Expr, BDD> predLookup = new Dictionary <Expr, BDD>(); Automaton <BDD> previouspatterns = Automaton <BDD> .MkEmpty(css); Automaton <BV2> N = Automaton <BV2> .MkFull(css2); var hasNoEndAnchor = new HashSet <int>(); for (int i = 0; i < repl.CaseCount; i++) { replacecase rcase = repl.GetCase(i); var pat = "^" + rcase.Pattern.val; var M = css.Convert("^" + rcase.Pattern.val, System.Text.RegularExpressions.RegexOptions.Singleline).Determinize().Minimize(); #region check that the pattern is a feasible nonempty sequence if (M.IsEmpty) { throw new BekParseException(string.Format("Semantic error: pattern {0} is infeasible.", rcase.Pattern.ToString())); } int _K; if (!M.CheckIfSequence(out _K)) { throw new BekParseException(string.Format("Semantic error: pattern {0} is not a sequence.", rcase.Pattern.ToString())); } if (_K == 0) { throw new BekParseException(string.Format("Semantic error: empty pattern {0} is not allowed.", rcase.Pattern.ToString())); } K = Math.Max(_K, K); #endregion var liftedMoves = new List <Move <BV2> >(); var st = M.InitialState; var newFinalState = M.MaxState + 1; var endAnchor = css.MkCharConstraint((char)i); //lift the moves to BV2 moves, adding end-markers while (!M.IsFinalState(st)) { var mv = M.GetMoveFrom(st); var pair_cond = new BV2(mv.Label, css.False); var liftedMove = new Move <BV2>(mv.SourceState, mv.TargetState, pair_cond); liftedMoves.Add(liftedMove); if (M.IsFinalState(mv.TargetState)) { var end_cond = new BV2(css.False, endAnchor); if (M.IsLoopState(mv.TargetState)) { hasNoEndAnchor.Add(i); //var loop_cond = css2.MkNot(end_cond); //var loopMove = new Move<BV2>(mv.TargetState, mv.TargetState, loop_cond); //liftedMoves.Add(loopMove); } var endMove = new Move <BV2>(mv.TargetState, newFinalState, end_cond); liftedMoves.Add(endMove); } st = mv.TargetState; } var N_i = Automaton <BV2> .Create(css2, M.InitialState, new int[] { newFinalState }, liftedMoves); //Microsoft.Automata.Visualizer.ToDot(N_i, "N" + i , "C:\\Automata\\Docs\\Papers\\Bex\\N" + i +".dot", x => "(" + css.PrettyPrint(x.First) + "," + css.PrettyPrint(x.Second) + ")"); N = N.Intersect(N_i.Complement()); #region other approach: disallow overlapping patterns //Visualizer.ShowGraph(M2.Complement(css2), "M2", lab => { return "<" + css.PrettyPrint(lab.First) + "," + css.PrettyPrint(lab.Second) + ">"; }); //note: keep here the original pattern, add only the start anchor to synchronize prefixes //var thispattern = css.Convert("^" + rcase.Pattern.val, System.Text.RegularExpressions.RegexOptions.Singleline).Determinize(css).Minimize(css); //var thispattern1 = thispattern.Minus(previouspatterns, css); //Visualizer.ShowGraph(thispattern1, "test", css.PrettyPrint); //#region check that thispattern does not overlap with any previous pattern //var common = thispattern.Intersect(previouspatterns, css); //if (!(common.IsEmpty)) //{ // int j = 0; // while ((j < i) && css.Convert("^" + repl.GetCase(j).Pattern.val, // System.Text.RegularExpressions.RegexOptions.Singleline).Determinize(css).Intersect(thispattern, css).IsEmpty) // j++; // throw new BekParseException(rcase.id.line, rcase.id.pos, string.Format("Semantic error: pattern {0} overlaps pattern {1}.", // rcase.Pattern.ToString(), repl.GetCase(j).Pattern.ToString())); //} //previouspatterns = previouspatterns.Union(thispattern).RemoveEpsilons(css.MkOr); //TBD: better union //#endregion #endregion } N = N.Complement().Minimize(); //Microsoft.Automata.Visualizer.ShowGraph(N, "N", x => "<" + css.PrettyPrint(x.First) + "," + css.PrettyPrint(x.Second) + ">"); //Microsoft.Automata.Visualizer.ToDot(N, "N","C:\\Automata\\Docs\\Papers\\Bex\\N.dot", x => "(" + css.PrettyPrint(x.First) + "," + css.PrettyPrint(x.Second) + ")"); var D = new Dictionary <int, int>(); var G = new Dictionary <int, BDD>(); #region compute distance from initial state and compute guard unions var S = new Stack <int>(); D[N.InitialState] = 0; G[N.InitialState] = css.False; S.Push(N.InitialState); while (S.Count > 0) { var q = S.Pop(); foreach (var move in N.GetMovesFrom(q)) { G[q] = css.MkOr(G[q], move.Label.Item1); var p = move.TargetState; var d = D[q] + 1; if (!(N.IsFinalState(p)) && !D.ContainsKey(p)) { D[p] = d; G[p] = css.False; S.Push(p); } if (!(N.IsFinalState(p)) && D[p] != d) { throw new BekException(string.Format("Unexpected error, inconsitent distances {0} and {1} to state {2}", D[p], d, p)); } } } #endregion #region check that outputs do not have out of bound variables foreach (var fs in N.GetFinalStates()) { foreach (var move in N.GetMovesTo(fs)) { if (move.Label.Item2.IsEmpty) { throw new BekException("Internal error: missing end anchor"); } //if (!css.IsSingleton(move.Condition.Second)) //{ // var one = (int)css.GetMin(move.Condition.Second); // var two = (int)css.GetMax(move.Condition.Second); // throw new BekParseException(repl.GetCase(two).id.line, repl.GetCase(two).id.pos, string.Format("Ambiguous replacement patterns {0} and {1}.", repl.GetCase(one).Pattern, repl.GetCase(two).Pattern)); //} //pick the minimum case identifer when there are several, essentially pick the earliest case int id = (int)css.GetMin(move.Label.Item2); int distFromRoot = D[move.SourceState]; var e = repl.GetCase(id).Output; HashSet <int> vars = new HashSet <int>(); foreach (var v in e.GetBoundVars()) { if (v.GetVarId() >= distFromRoot) { throw new BekParseException(v.line, v.pos, string.Format("Syntax error: pattern variable '{0}' is out ouf bounds, valid range is from '#0' to '#{1}']", v.name, distFromRoot - 1)); } } } } #endregion int finalState = N.FinalState; K = K - 1; //this many registers are needed var zeroChar = stb.Solver.MkCharExpr('\0'); var STmoves = new List <Move <Rule <Expr> > >(); var STstates = new HashSet <int>(); var STdelta = new Dictionary <int, List <Move <Rule <Expr> > > >(); var STdeltaInv = new Dictionary <int, List <Move <Rule <Expr> > > >(); var FinalSTstates = new HashSet <int>(); var STdeletedMoves = new HashSet <Move <Rule <Expr> > >(); Action <Move <Rule <Expr> > > STmovesAdd = r => { var p = r.SourceState; var q = r.TargetState; STmoves.Add(r); if (STstates.Add(p)) { STdelta[p] = new List <Move <Rule <Expr> > >(); STdeltaInv[p] = new List <Move <Rule <Expr> > >(); } if (STstates.Add(q)) { STdelta[q] = new List <Move <Rule <Expr> > >(); STdeltaInv[q] = new List <Move <Rule <Expr> > >(); } if (r.Label.IsFinal) { FinalSTstates.Add(p); } STdelta[p].Add(r); STdeltaInv[q].Add(r); }; var regsorts = new Sort[K]; for (int j = 0; j < K; j++) { regsorts[j] = stb.Solver.CharSort; } var regsort = stb.Solver.MkTupleSort(regsorts); var regvar = stb.MkRegister(regsort); var initialRegisterValues = new Expr[K]; for (int j = 0; j < K; j++) { initialRegisterValues[j] = zeroChar; } var initialRegister = stb.Solver.MkTuple(initialRegisterValues); Predicate <int> IsCaseEndState = s => { return(N.OutDegree(s) == 1 && N.GetMoveFrom(s).Label.Item1.IsEmpty); }; #region compute the forward moves and the completion moves var V = new HashSet <int>(); S.Push(N.InitialState); while (S.Count > 0) { var p = S.Pop(); #region forward moves foreach (var move in N.GetMovesFrom(p)) { var q = move.TargetState; //this move occurs if p has both an end-move and a non-end-move //note that if p is an case-end-state then it is never pushed to S if (N.IsFinalState(q)) { continue; } var distance = D[p]; Expr chExpr; Expr chPred; MkExprPred(move.Label.Item1, out chExpr, out chPred); predLookup[chPred] = move.Label.Item1; Expr[] regUpds = new Expr[K]; for (int i = 0; i < K; i++) { if (i == distance) { regUpds[i] = chExpr; } else //if (i < distance) { regUpds[i] = stb.Solver.MkProj(i, regvar); } //else // regUpds[i] = zeroChar; } Expr regExpr = stb.Solver.MkTuple(regUpds); var moveST = stb.MkRule(p, q, chPred, regExpr); //there are no yields STmovesAdd(moveST); if (V.Add(q) && !IsCaseEndState(q)) { S.Push(q); } } #endregion #region completion is only enabled if there exists an else case if (repl.HasElseCase) { var guards = G[p]; var guards0 = G[N.InitialState]; #region nonmatching cases to the initial state var nomatch = css.MkNot(css.MkOr(guards, guards0)); if (!nomatch.IsEmpty) { Expr chExpr; Expr nomatchPred; MkExprPred(nomatch, out chExpr, out nomatchPred); predLookup[nomatchPred] = nomatch; var else_yields_list = new List <Expr>(); for (int i = 0; i < D[p]; i++) { else_yields_list.AddRange(GetElseYieldInstance(repl.ElseOutput, stb.Solver.MkProj(i, regvar))); } else_yields_list.AddRange(GetElseYieldInstance(repl.ElseOutput, stb.MkInputVariable(stb.Solver.CharSort))); var else_yields = else_yields_list.ToArray(); var resetMove = stb.MkRule(p, N.InitialState, nomatchPred, initialRegister, else_yields); STmovesAdd(resetMove); } #endregion #region matching cases via the initial state foreach (var move0 in N.GetMovesFrom(N.InitialState)) { var g0 = move0.Label.Item1; var match = css.MkAnd(css.MkNot(guards), g0); if (!match.IsEmpty) { Expr chExpr; Expr matchPred; MkExprPred(match, out chExpr, out matchPred); predLookup[matchPred] = match; var resetYieldsList = new List <Expr>(); //for all unprocessed inputs produce the output yield according to the else case for (int i = 0; i < D[p]; i++) { resetYieldsList.AddRange(GetElseYieldInstance(repl.ElseOutput, stb.Solver.MkProj(i, regvar))); } var resetYields = resetYieldsList.ToArray(); Expr[] regupd = new Expr[K]; regupd[0] = chExpr; for (int j = 1; j < K; j++) { regupd[j] = zeroChar; } var regupdExpr = stb.Solver.MkTuple(regupd); var resetMove = stb.MkRule(p, move0.TargetState, matchPred, regupdExpr, resetYields); STmovesAdd(resetMove); } } #endregion } #endregion } #endregion foreach (var last_move in N.GetMovesTo(N.FinalState)) { //i is the case identifier int i = (int)css.GetMin(last_move.Label.Item2); if (hasNoEndAnchor.Contains(i)) { #region this corresponds to looping back to the initial state on the given input //the final outputs produced after a successful pattern match #region compute the output terms int distFromRoot = D[last_move.SourceState]; Func <ident, Expr> registerMap = id => { // --- already checked I think --- if (!id.IsVar || id.GetVarId() >= distFromRoot) { throw new BekParseException(id.Line, id.Pos, string.Format("illeagal variable '{0}' in output", id.name)); } if (id.GetVarId() == distFromRoot - 1) //the last reg update refers to the current variable { return(stb.MkInputVariable(stb.Solver.CharSort)); } else { return(stb.Solver.MkProj(id.GetVarId(), regvar)); } }; Expr[] yields; var outp = repl.GetCase(i).Output; if (outp is strconst) { var s = ((strconst)outp).val; yields = Array.ConvertAll(s.ToCharArray(), c => this.str_handler.iter_handler.expr_handler.Convert(new charconst("'" + StringUtility.Escape(c) + "'"), registerMap)); } else //must be an explicit list construct { if (!(outp is functioncall) || !((functioncall)outp).id.name.Equals("string")) { throw new BekParseException("Invalid pattern output."); } var s = ((functioncall)outp).args; yields = Array.ConvertAll(s.ToArray(), e => this.str_handler.iter_handler.expr_handler.Convert(e, registerMap)); } #endregion //shortcut all the incoming transitions to the initial state foreach (var move in STdeltaInv[last_move.SourceState]) { //go to the initial state, i.e. the matching raps around int p = move.SourceState; int q0 = N.InitialState; List <Expr> yields1 = new List <Expr>(move.Label.Yields); //incoming yields are yields1.AddRange(yields); var rule = stb.MkRule(p, q0, move.Label.Guard, initialRegister, yields1.ToArray()); STmovesAdd(rule); //STdeletedMoves.Add(move); STmoves.Remove(move); //the move has been replaced } #endregion } else { #region this is the end of the input stream case #region compute the output terms int distFromRoot = D[last_move.SourceState]; Func <ident, Expr> registerMap = id => { if (!id.IsVar || id.GetVarId() >= distFromRoot) { throw new BekParseException(id.Line, id.Pos, string.Format("illeagal variable '{0}' in output", id.name)); } return(stb.Solver.MkProj(id.GetVarId(), regvar)); }; Expr[] yields; var outp = repl.GetCase(i).Output; if (outp is strconst) { var s = ((strconst)outp).val; yields = Array.ConvertAll(s.ToCharArray(), c => this.str_handler.iter_handler.expr_handler.Convert(new charconst("'" + c.ToString() + "'"), registerMap)); } else //must be an explicit list construct { if (!(outp is functioncall) || !((functioncall)outp).id.name.Equals("string")) { throw new BekParseException("Invalid pattern output."); } var s = ((functioncall)outp).args; yields = Array.ConvertAll(s.ToArray(), e => this.str_handler.iter_handler.expr_handler.Convert(e, registerMap)); } #endregion int p = last_move.SourceState; var rule = stb.MkFinalOutput(p, stb.Solver.True, yields); STmovesAdd(rule); #endregion } } if (repl.HasElseCase) { #region final completion (upon end of input) for all non-final states foreach (var p in STstates) { if (!FinalSTstates.Contains(p) && !IsCaseEndState(p)) //there is no final rule for p, so add the default one { Expr[] finalYields; finalYields = new Expr[D[p]]; for (int i = 0; i < finalYields.Length; i++) { finalYields[i] = stb.Solver.MkProj(i, regvar); } var p_finalMove = stb.MkFinalOutput(p, stb.Solver.True, finalYields); STmovesAdd(p_finalMove); } } #endregion } else { //in this case there is a final rule from the initial state var q0_finalMove = stb.MkFinalOutput(N.InitialState, stb.Solver.True); STmovesAdd(q0_finalMove); } var resST = stb.MkST(name, initialRegister, stb.Solver.CharSort, stb.Solver.CharSort, regsort, N.InitialState, STmoves); var resSTb = new STModel(stb.Solver, name, stb.Solver.CharSort, stb.Solver.CharSort, regsort, initialRegister, N.InitialState); //create STb from the moves, we use here the knowledge that the ST is deterministic //we also use the lookuptable of conditions to eliminate dead code //resST.ShowGraph(); //resST.ToDot("C:\\Automata\\Docs\\Papers\\Bex\\B.dot"); #region compute the rules of the resulting STb //V.Clear(); //S.Push(resST.InitialState); //V.Add(resST.InitialState); foreach (var st in resST.GetStates()) { var condUnion = css.False; var st_moves = new List <Move <Rule <Expr> > >(); foreach (var move in resST.GetNonFinalMovesFrom(st)) { condUnion = css.MkOr(condUnion, predLookup[move.Label.Guard]); st_moves.Add(move); } BranchingRule <Expr> st_rule; if (st_moves.Count > 0) { //collect all rules with singleton guards and put them into a switch statement var st_rules1 = new List <KeyValuePair <Expr, BranchingRule <Expr> > >(); var st_moves2 = new List <Move <Rule <Expr> > >(); foreach (var move in st_moves) { if (css.ComputeDomainSize(predLookup[move.Label.Guard]) == 1) { var v = stb.Solver.MkNumeral(css.Choose(predLookup[move.Label.Guard]), stb.Solver.CharSort); var r = new BaseRule <Expr>(new Sequence <Expr>(move.Label.Yields), move.Label.Update, move.TargetState); st_rules1.Add(new KeyValuePair <Expr, BranchingRule <Expr> >(v, r)); } else { st_moves2.Add(move); } } BranchingRule <Expr> defaultcase = new UndefRule <Expr>("reject"); //make st_moves2 into an ite rule if (st_moves2.Count > 0) { for (int j = st_moves2.Count - 1; j >= 0; j--) { var r = new BaseRule <Expr>(new Sequence <Expr>(st_moves2[j].Label.Yields), st_moves2[j].Label.Update, st_moves2[j].TargetState); if (j == (st_moves2.Count - 1) && condUnion.IsFull) { defaultcase = r; } else { defaultcase = new IteRule <Expr>(st_moves2[j].Label.Guard, r, defaultcase); } } } else if (condUnion.IsFull) { defaultcase = st_rules1[st_rules1.Count - 1].Value; st_rules1.RemoveAt(st_rules1.Count - 1); } if (st_rules1.Count == 0) { st_rule = defaultcase; } else { st_rule = new SwitchRule <Expr>(stb.MkInputVariable(stb.Solver.CharSort), defaultcase, st_rules1.ToArray()); } } else { st_rule = new UndefRule <Expr>("reject"); } resSTb.AssignRule(st, st_rule); var st_finalrules = new List <Rule <Expr> >(resST.GetFinalRules(st)); if (st_finalrules.Count > 1) { throw new BekException("Unexpected error: multiple final rules per state."); } if (st_finalrules.Count > 0) { resSTb.AssignFinalRule(st, new BaseRule <Expr>(new Sequence <Expr>(st_finalrules[0].Yields), initialRegister, st)); } } resSTb.ST = resST; resST.STb = resSTb; #endregion return(resSTb); }
public void TestSTbSimplify() { string utf8decode_bek = @" function fuse(r,c) = ((r << 6) | (c & 0x3F)); function one(c) = ((0 <= c) && (c <= 0x7F)); function C2_DF(c) = ((0xC2 <= c) && (c <= 0xDF)); function E1_EF(c) = ((0xE1 <= c) && (c <= 0xEF)); function A0_BF(c) = ((0xA0 <= c) && (c <= 0xBF)); function x80_BF(c) = ((0x80 <= c) && (c <= 0xBF)); function x80_9F(c) = ((0x80 <= c) && (c <= 0x9F)); program utf8decode(input){ return iter(c in input)[q := 0; r := 0;] { case (q == 0): if (one(c)) {yield (c);} else if (C2_DF(c)) {q := 2; r := (c & 0x1F);} // ------ 2 bytes -------- else if (c == 0xE0) {q := 4; r := (c & 0x0F);} // ------ 3 bytes -------- else if (c == 0xED) {q := 5; r := (c & 0x0F);} // ------ 3 bytes -------- else if (E1_EF(c)) {q := 3; r := (c & 0x0F);} // ------ 3 bytes -------- else {raise InvalidInput;} case (q == 2): if (x80_BF(c)) {q := 0; yield(fuse(r,c)); r := 0;} else {raise InvalidInput;} case (q == 3): if (x80_BF(c)) {q := 2; r := fuse(r,c);} else {raise InvalidInput;} case (q == 4): if (A0_BF(c)) {q := 2; r := fuse(r,c);} else {raise InvalidInput;} case (q == 5): if (x80_9F(c)) {q := 2; r := fuse(r,c);} else {raise InvalidInput;} end case (!(q == 0)): raise InvalidInput; }; } "; Z3Provider solver = new Z3Provider(BitWidth.BV16); var dec = BekConverter.BekToSTb(solver, utf8decode_bek); var utf8decode = dec.ExploreBools(); Sort bv32 = solver.MkBitVecSort(32); Sort outSort = solver.MkTupleSort(solver.StringSort, bv32); var initReg = solver.MkTuple(solver.GetNil(solver.StringSort), solver.MkNumeral(0, bv32)); var regVar = solver.MkVar(1, outSort); var reg1 = solver.MkProj(1, regVar); var reg0 = solver.MkProj(0, regVar); STb <FuncDecl, Expr, Sort> parse = new STbModel(solver, "Parse", solver.CharacterSort, outSort, outSort, initReg, 0); var letter = solver.MkOr( //solver.MkAnd(solver.MkCharLe(solver.MkCharExpr('\xC0'), solver.CharVar), // solver.MkCharLe(solver.CharVar, solver.MkCharExpr('\xFF'))), solver.MkAnd(solver.MkCharLe(solver.MkCharExpr('a'), solver.CharVar), solver.MkCharLe(solver.CharVar, solver.MkCharExpr('z'))), solver.MkAnd(solver.MkCharLe(solver.MkCharExpr('A'), solver.CharVar), solver.MkCharLe(solver.CharVar, solver.MkCharExpr('Z')))); //var not_letter = solver.MkNot(letter); var digit = solver.MkAnd(solver.MkCharLe(solver.MkCharExpr('0'), solver.CharVar), solver.MkCharLe(solver.CharVar, solver.MkCharExpr('9'))); var nl = solver.MkEq(solver.CharVar, solver.MkCharExpr('\n')); var space = solver.MkEq(solver.CharVar, solver.MkCharExpr(' ')); //var not_nl = solver.MkNot(nl); var _0 = solver.MkNumeral((int)'0', bv32); //var z = solver.Z3.MkFreshConst("z", solver.CharacterSort); //var constr = solver.MkNot(solver.Z3.MkExists(new Expr[] { z }, nl.Substitute(solver.CharVar, z))); ////var constr = nl.Substitute(solver.CharVar, z); //solver.Z3S.Push(); //solver.Z3S.Assert((BoolExpr)solver.MkNot(constr)); //var status = solver.Check(); //var m = solver.Z3S.Model; //var zval = m.Evaluate(z, true); //solver.Z3S.Pop(); var loop_0 = new BaseRule <Expr>(Sequence <Expr> .Empty, regVar, 0); var brule0_1 = new BaseRule <Expr>(Sequence <Expr> .Empty, solver.MkTuple(solver.MkListCons(solver.CharVar, reg0), reg1), 1); var rule0 = new IteRule <Expr>(letter, brule0_1, new IteRule <Expr>(space, loop_0, UndefRule <Expr> .Default)); parse.AssignRule(0, rule0); var brule1_2 = new BaseRule <Expr>(Sequence <Expr> .Empty, solver.MkTuple(solver.MkListCons(solver.CharVar, reg0), reg1), 2); var brule_4 = new BaseRule <Expr>(Sequence <Expr> .Empty, regVar, 4); var rule1 = new IteRule <Expr>(letter, brule1_2, new IteRule <Expr>(space, brule_4, UndefRule <Expr> .Default)); parse.AssignRule(1, rule1); var brule2_3 = new BaseRule <Expr>(Sequence <Expr> .Empty, solver.MkTuple(solver.MkListCons(solver.CharVar, reg0), reg1), 4); var rule2 = new IteRule <Expr>(letter, brule2_3, new IteRule <Expr>(space, brule_4, UndefRule <Expr> .Default)); parse.AssignRule(2, rule2); var bv32var = solver.Z3.MkZeroExt(16, (BitVecExpr)solver.CharVar); var brule4_5 = new BaseRule <Expr>(Sequence <Expr> .Empty, solver.MkTuple(reg0, solver.MkBvAdd( solver.MkBvMul(solver.MkNumeral(10, bv32), reg1), solver.MkBvSub(bv32var, _0))), 5); var rule4 = new IteRule <Expr>(digit, brule4_5, new IteRule <Expr>(space, brule_4, UndefRule <Expr> .Default)); parse.AssignRule(4, rule4); var brule_0 = new BaseRule <Expr>(Sequence <Expr> .Empty.Append(regVar), initReg, 0); var brule_7 = new BaseRule <Expr>(Sequence <Expr> .Empty, regVar, 7); var brule5_6 = new BaseRule <Expr>(Sequence <Expr> .Empty, solver.MkTuple(reg0, solver.MkBvAdd( solver.MkBvMul(solver.MkNumeral(10, bv32), reg1), solver.MkBvSub(bv32var, _0))), 6); var rule5 = new IteRule <Expr>(digit, brule5_6, new IteRule <Expr>(nl, brule_0, new IteRule <Expr>(space, brule_7, UndefRule <Expr> .Default))); parse.AssignRule(5, rule5); var brule6_7 = new BaseRule <Expr>(Sequence <Expr> .Empty, solver.MkTuple(reg0, solver.MkBvAdd( solver.MkBvMul(solver.MkNumeral(10, bv32), reg1), solver.MkBvSub(bv32var, _0))), 7); var rule6 = new IteRule <Expr>(digit, brule6_7, new IteRule <Expr>(nl, brule_0, new IteRule <Expr>(space, brule_7, UndefRule <Expr> .Default))); parse.AssignRule(6, rule6); var rule7 = new IteRule <Expr>(nl, brule_0, new IteRule <Expr>(space, brule_7, UndefRule <Expr> .Default)); parse.AssignRule(7, rule7); parse.AssignFinalRule(0, new BaseRule <Expr>(Sequence <Expr> .Empty, initReg, 0)); var comp = utf8decode.Compose(parse); //utf8decode.ToST().ShowGraph(); //parse.ToST().ShowGraph(); //comp.ToST().ShowGraph(); //var comp1 = new STbSimulator<FuncDecl,Expr,Sort>(comp); //comp1.Explore(); //Console.WriteLine(comp1.exploredSteps); //var rules = Array.ConvertAll(comp1.UncoveredMoves.ToArray(), r => new Tuple<int, int>(r.Item3.SourceState, r.Item3.TargetState)); var simpl = comp.Simplify(); Assert.AreEqual <int>(35, comp.StateCount); Assert.AreEqual <int>(7, simpl.StateCount); //simpl.ShowGraph(); }
STb <FuncDecl, Expr, Sort> Generate() { var name = DeclarationType.ContainingNamespace.Name + "." + (DeclarationType.ContainingType == null ? "" : DeclarationType.ContainingType.Name + ".") + DeclarationType.Name; Console.WriteLine("XPath " + name); var parser = new XPathParser <IXPathNode>(); IXPathNode root; try { root = parser.Parse(_xpath, new XPathNodeBuilder()); Console.WriteLine(root); } catch (XPathParserException e) { throw new TransducerCompilationException("XPath parsing failed", e); } var resultSort = _ctx.MkBitVecSort(32); var levelCounterSort = _ctx.MkBitVecSort(32); var regSort = _ctx.MkTupleSort(resultSort, levelCounterSort); var initReg = _ctx.MkTuple(_ctx.MkNumeral(0, resultSort), _ctx.MkNumeral(0, levelCounterSort)); var stb = new STb <FuncDecl, Expr, Sort>(_ctx, "stb", _ctx.CharSort, _ctx.MkBitVecSort(32), regSort, initReg, 0); int freeState = 1; Func <int> nextState = () => freeState++; var resultProj = _ctx.MkProj(0, stb.RegVar); var levelCounterProj = _ctx.MkProj(1, stb.RegVar); Func <int, IgnorerInfo> CreateIgnorer = (exitState) => { IgnorerInfo info = new IgnorerInfo(); int outsideTagState = nextState(); int freshTagState = nextState(); int openingTagState = nextState(); int standaloneTagState = nextState(); int closingTagState = nextState(); stb.AssignRule(outsideTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '<'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, freshTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, outsideTagState))); stb.AssignRule(freshTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, closingTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, openingTagState))); var counterOne = _ctx.MkNumeral(1, levelCounterSort); var levelCounterInc = _ctx.MkTuple(resultProj, _ctx.MkBvAdd(levelCounterProj, counterOne)); stb.AssignRule(openingTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterInc, outsideTagState), new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, standaloneTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, openingTagState)))); var counterZero = _ctx.MkNumeral(0, levelCounterSort); var levelCounterZeroed = _ctx.MkTuple(resultProj, counterZero); stb.AssignRule(standaloneTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new IteRule <Expr>(_ctx.MkEq(levelCounterProj, counterZero), new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterZeroed, exitState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, outsideTagState)), new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, standaloneTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, openingTagState)))); var levelCounterDec = _ctx.MkTuple(resultProj, _ctx.MkBvSub(levelCounterProj, counterOne)); stb.AssignRule(closingTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new IteRule <Expr>(_ctx.MkEq(levelCounterProj, counterOne), new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterZeroed, exitState), new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterDec, outsideTagState)), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, closingTagState))); info.MoveToTagOpening = new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterZeroed, openingTagState); info.MoveToTagOpeningOrStandalone = new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterZeroed, standaloneTagState), info.MoveToTagOpening); var levelCounterSet = _ctx.MkTuple(resultProj, counterOne); info.MoveToOutsideTag = new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterSet, outsideTagState); return(info); }; var next = root; int?parentState = null; int startState = stb.InitialState; int childState = nextState(); var zeroResult = _ctx.MkTuple(_ctx.MkNumeral(0, resultSort), levelCounterProj); while (next != null) { XPathAxisNode current; var step = next as XPathStepNode; if (step != null) { current = step.Left as XPathAxisNode; next = step.Right; } else { current = next as XPathAxisNode; next = null; } if (current.Axis == XPathAxis.Root) { continue; } if (current == null) { throw new TransducerCompilationException("Unsupported XPath node type: " + next.GetType()); } if (current.Axis != XPathAxis.Child) { throw new TransducerCompilationException("Unsupported axis: " + current.Axis); } if (current.Type != System.Xml.XPath.XPathNodeType.Element) { throw new TransducerCompilationException("Unsupported node type: " + current.Type); } int freshTagState = nextState(); int closingTagState = nextState(); int standaloneMatchState = nextState(); int matchedOpeningTagState = nextState(); int matchedStandaloneTagState = nextState(); var ignorer = CreateIgnorer(startState); stb.AssignRule(startState, new IteRule <Expr>(EqualsChar(stb.InputVar, '<'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, freshTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, startState))); int matchState = freshTagState; int nextMatchState = nextState(); bool first = true; foreach (char c in current.Label) { STbRule <Expr> matchRule; if (first) { matchRule = new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, closingTagState), new IteRule <Expr>(EqualsChar(stb.InputVar, c), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, nextMatchState), new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), ignorer.MoveToOutsideTag, ignorer.MoveToTagOpening))); first = false; } else { matchRule = new IteRule <Expr>(EqualsChar(stb.InputVar, c), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, nextMatchState), new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), ignorer.MoveToOutsideTag, ignorer.MoveToTagOpeningOrStandalone)); } stb.AssignRule(matchState, matchRule); matchState = nextMatchState; nextMatchState = nextState(); } stb.AssignRule(closingTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), parentState != null ? (STbRule <Expr>) new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, parentState.Value) : new UndefRule <Expr>(), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, closingTagState))); stb.AssignRule(matchState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new BaseRule <Expr>(Sequence <Expr> .Empty, zeroResult, childState), new IteRule <Expr>(EqualsChar(stb.InputVar, ' '), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, matchedOpeningTagState), new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, standaloneMatchState), ignorer.MoveToTagOpening)))); stb.AssignRule(standaloneMatchState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, startState), new UndefRule <Expr>())); stb.AssignRule(matchedOpeningTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new BaseRule <Expr>(Sequence <Expr> .Empty, zeroResult, childState), new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, matchedStandaloneTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, matchedOpeningTagState)))); stb.AssignRule(matchedStandaloneTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, startState), new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, matchedStandaloneTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, matchedOpeningTagState)))); parentState = startState; startState = childState; childState = nextState(); } Func <Expr, Expr> AddZeros = (c) => { uint k = (uint)(32 - (int)_ctx.CharSetProvider.Encoding); if (k == 0) { return(c); } else { return(_ctx.MkZeroExt(k, c)); } }; var toIntUpdate = _ctx.MkTuple( _ctx.MkBvAdd(_ctx.MkBvMul(_ctx.MkNumeral(10, resultSort), resultProj), _ctx.MkBvSub(AddZeros(stb.InputVar), _ctx.MkNumeral((int)'0', resultSort))), levelCounterProj); var expectSlashState = nextState(); var scanTagState = nextState(); stb.AssignRule(startState, new IteRule <Expr>(EqualsChar(stb.InputVar, '<'), new BaseRule <Expr>(new Sequence <Expr>(resultProj), zeroResult, expectSlashState), new BaseRule <Expr>(Sequence <Expr> .Empty, toIntUpdate, startState))); stb.AssignRule(expectSlashState, new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, scanTagState), new UndefRule <Expr>())); stb.AssignRule(scanTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), parentState != null ? (STbRule <Expr>) new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, parentState.Value) : new UndefRule <Expr>(), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, scanTagState))); Console.WriteLine(stb.StateCount); foreach (var state in stb.States) { stb.AssignFinalRule(state, new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, state)); } if (ShowGraphStages.Count > 0) { stb.ToST().ShowGraph(); } return(stb); }
public void TestSTbSimplify() { string utf8decode_bek = @" function fuse(r,c) = ((r << 6) | (c & 0x3F)); function one(c) = ((0 <= c) && (c <= 0x7F)); function C2_DF(c) = ((0xC2 <= c) && (c <= 0xDF)); function E1_EF(c) = ((0xE1 <= c) && (c <= 0xEF)); function A0_BF(c) = ((0xA0 <= c) && (c <= 0xBF)); function x80_BF(c) = ((0x80 <= c) && (c <= 0xBF)); function x80_9F(c) = ((0x80 <= c) && (c <= 0x9F)); program utf8decode(input){ return iter(c in input)[q := 0; r := 0;] { case (q == 0): if (one(c)) {yield (c);} else if (C2_DF(c)) {q := 2; r := (c & 0x1F);} // ------ 2 bytes -------- else if (c == 0xE0) {q := 4; r := (c & 0x0F);} // ------ 3 bytes -------- else if (c == 0xED) {q := 5; r := (c & 0x0F);} // ------ 3 bytes -------- else if (E1_EF(c)) {q := 3; r := (c & 0x0F);} // ------ 3 bytes -------- else {raise InvalidInput;} case (q == 2): if (x80_BF(c)) {q := 0; yield(fuse(r,c)); r := 0;} else {raise InvalidInput;} case (q == 3): if (x80_BF(c)) {q := 2; r := fuse(r,c);} else {raise InvalidInput;} case (q == 4): if (A0_BF(c)) {q := 2; r := fuse(r,c);} else {raise InvalidInput;} case (q == 5): if (x80_9F(c)) {q := 2; r := fuse(r,c);} else {raise InvalidInput;} end case (!(q == 0)): raise InvalidInput; }; } "; Z3Provider solver = new Z3Provider(BitWidth.BV16); var dec = BekConverter.BekToSTb(solver, utf8decode_bek); var utf8decode = dec.ExploreBools(); Sort bv32 = solver.MkBitVecSort(32); Sort outSort = solver.MkTupleSort(solver.StringSort, bv32); var initReg = solver.MkTuple(solver.GetNil(solver.StringSort), solver.MkNumeral(0,bv32)); var regVar = solver.MkVar(1,outSort); var reg1 = solver.MkProj(1, regVar); var reg0 = solver.MkProj(0, regVar); STb<FuncDecl, Expr, Sort> parse = new STbModel(solver, "Parse", solver.CharacterSort, outSort, outSort, initReg, 0); var letter = solver.MkOr(//solver.MkAnd(solver.MkCharLe(solver.MkCharExpr('\xC0'), solver.CharVar), // solver.MkCharLe(solver.CharVar, solver.MkCharExpr('\xFF'))), solver.MkAnd(solver.MkCharLe(solver.MkCharExpr('a'), solver.CharVar), solver.MkCharLe(solver.CharVar, solver.MkCharExpr('z'))), solver.MkAnd(solver.MkCharLe(solver.MkCharExpr('A'), solver.CharVar), solver.MkCharLe(solver.CharVar, solver.MkCharExpr('Z')))); //var not_letter = solver.MkNot(letter); var digit = solver.MkAnd(solver.MkCharLe(solver.MkCharExpr('0'), solver.CharVar), solver.MkCharLe(solver.CharVar, solver.MkCharExpr('9'))); var nl = solver.MkEq(solver.CharVar, solver.MkCharExpr('\n')); var space = solver.MkEq(solver.CharVar, solver.MkCharExpr(' ')); //var not_nl = solver.MkNot(nl); var _0 = solver.MkNumeral((int)'0', bv32); //var z = solver.Z3.MkFreshConst("z", solver.CharacterSort); //var constr = solver.MkNot(solver.Z3.MkExists(new Expr[] { z }, nl.Substitute(solver.CharVar, z))); ////var constr = nl.Substitute(solver.CharVar, z); //solver.Z3S.Push(); //solver.Z3S.Assert((BoolExpr)solver.MkNot(constr)); //var status = solver.Check(); //var m = solver.Z3S.Model; //var zval = m.Evaluate(z, true); //solver.Z3S.Pop(); var loop_0 = new BaseRule<Expr>(Sequence<Expr>.Empty, regVar, 0); var brule0_1 = new BaseRule<Expr>(Sequence<Expr>.Empty, solver.MkTuple(solver.MkListCons(solver.CharVar, reg0), reg1), 1); var rule0 = new IteRule<Expr>(letter, brule0_1, new IteRule<Expr>(space, loop_0, UndefRule<Expr>.Default)); parse.AssignRule(0, rule0); var brule1_2 = new BaseRule<Expr>(Sequence<Expr>.Empty, solver.MkTuple(solver.MkListCons(solver.CharVar, reg0), reg1), 2); var brule_4 = new BaseRule<Expr>(Sequence<Expr>.Empty, regVar, 4); var rule1 = new IteRule<Expr>(letter, brule1_2, new IteRule<Expr>(space, brule_4, UndefRule<Expr>.Default)); parse.AssignRule(1, rule1); var brule2_3 = new BaseRule<Expr>(Sequence<Expr>.Empty, solver.MkTuple(solver.MkListCons(solver.CharVar, reg0), reg1), 4); var rule2 = new IteRule<Expr>(letter, brule2_3, new IteRule<Expr>(space, brule_4, UndefRule<Expr>.Default)); parse.AssignRule(2, rule2); var bv32var = solver.Z3.MkZeroExt(16, (BitVecExpr)solver.CharVar); var brule4_5 = new BaseRule<Expr>(Sequence<Expr>.Empty, solver.MkTuple(reg0, solver.MkBvAdd( solver.MkBvMul(solver.MkNumeral(10,bv32),reg1), solver.MkBvSub(bv32var,_0))),5); var rule4 = new IteRule<Expr>(digit, brule4_5, new IteRule<Expr>(space, brule_4, UndefRule<Expr>.Default)); parse.AssignRule(4, rule4); var brule_0 = new BaseRule<Expr>(Sequence<Expr>.Empty.Append(regVar), initReg, 0); var brule_7 = new BaseRule<Expr>(Sequence<Expr>.Empty, regVar, 7); var brule5_6 = new BaseRule<Expr>(Sequence<Expr>.Empty, solver.MkTuple(reg0, solver.MkBvAdd( solver.MkBvMul(solver.MkNumeral(10, bv32), reg1), solver.MkBvSub(bv32var, _0))), 6); var rule5 = new IteRule<Expr>(digit, brule5_6, new IteRule<Expr>(nl, brule_0, new IteRule<Expr>(space, brule_7, UndefRule<Expr>.Default))); parse.AssignRule(5, rule5); var brule6_7 = new BaseRule<Expr>(Sequence<Expr>.Empty, solver.MkTuple(reg0, solver.MkBvAdd( solver.MkBvMul(solver.MkNumeral(10, bv32), reg1), solver.MkBvSub(bv32var, _0))), 7); var rule6 = new IteRule<Expr>(digit, brule6_7, new IteRule<Expr>(nl, brule_0, new IteRule<Expr>(space, brule_7, UndefRule<Expr>.Default))); parse.AssignRule(6, rule6); var rule7 = new IteRule<Expr>(nl, brule_0, new IteRule<Expr>(space, brule_7, UndefRule<Expr>.Default)); parse.AssignRule(7, rule7); parse.AssignFinalRule(0, new BaseRule<Expr>(Sequence<Expr>.Empty, initReg, 0)); var comp = utf8decode.Compose(parse); //utf8decode.ToST().ShowGraph(); //parse.ToST().ShowGraph(); //comp.ToST().ShowGraph(); //var comp1 = new STbSimulator<FuncDecl,Expr,Sort>(comp); //comp1.Explore(); //Console.WriteLine(comp1.exploredSteps); //var rules = Array.ConvertAll(comp1.UncoveredMoves.ToArray(), r => new Tuple<int, int>(r.Item3.SourceState, r.Item3.TargetState)); var simpl = comp.Simplify(); Assert.AreEqual<int>(35, comp.StateCount); Assert.AreEqual<int>(7, simpl.StateCount); //simpl.ShowGraph(); }
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); } }