STb <FuncDecl, Expr, Sort> GenerateEncoder()
        {
            var ctx = _automataCtx.Z3;

            Expr inputVar    = _automataCtx.MkVar(0, ctx.MkBitVecSort(8));
            Expr registerVar = _automataCtx.MkVar(1, _automataCtx.MkTupleSort());
            Sort outputSort  = ctx.BoolSort;
            var  stb         = new STb <FuncDecl, Expr, Sort>(_automataCtx, DeclarationType.Name, inputVar.Sort, outputSort, registerVar.Sort, _automataCtx.MkTuple(), 0);

            var leafPatterns = new Dictionary <byte, bool[]>();

            FindLeafPatterns(leafPatterns, _tree, new Stack <bool>());

            var patterns = new bool[256][];

            foreach (var entry in leafPatterns)
            {
                patterns[entry.Key] = entry.Value;
            }
            Debug.Assert(patterns.Select((x, i) => patterns.Select((y, j) => i == j || x.Length != y.Length || x.Zip(y, (a, b) => Tuple.Create(a, b)).Any(z => z.Item1 != z.Item2)).All(z => z)).All(z => z));
            Debug.Assert(patterns.All(x => x != null), "Internal Huffman tree is missing leaves");

            stb.AssignRule(0, GetBinarySearchRule(ctx, (BitVecExpr)inputVar, registerVar, patterns, 0, patterns.Length));
            stb.AssignFinalRule(0, new BaseRule <Expr>(Sequence <Expr> .Empty, registerVar, 0));

            stb = stb.Compose(GenerateToBytes());
            stb = stb.ExploreBools();
            if (ShowGraphStages.Count > 0)
            {
                stb.ToST().ShowGraph();
            }
            return(stb);
        }
Exemple #2
0
        STb <FuncDecl, Expr, Sort> Generate()
        {
            var name = DeclarationType.ContainingNamespace.Name + "." +
                       (DeclarationType.ContainingType == null ? "" : DeclarationType.ContainingType.Name + ".") + DeclarationType.Name;

            Console.WriteLine("Regex " + name);

            var builder = new STbFromRegexBuilder <FuncDecl, Expr, Sort>(_automataCtx);
            var stb     = builder.Mk(_regex, "value", _type);

            if ((stb.OutputSort is TupleSort || _automataCtx.IsTupleSort(stb.OutputSort)) && _automataCtx.GetTupleConstructor(stb.OutputSort).Arity == 1)
            {
                var fieldDecl = _automataCtx.GetTupleField(stb.OutputSort, 0);
                var reg       = _automataCtx.MkTuple();
                var projector = new STb <FuncDecl, Expr, Sort>(_automataCtx, "Project", stb.OutputSort, fieldDecl.Range, reg.Sort, reg, 0);
                projector.AssignRule(0, new BaseRule <Expr>(new Sequence <Expr>(fieldDecl.Apply(projector.InputVar)), reg, 0));
                projector.AssignFinalRule(0, new BaseRule <Expr>(Sequence <Expr> .Empty, reg, 0));
                stb = stb.Compose(projector).Flatten();
            }

            if (ShowGraphStages.Count > 0)
            {
                stb.ToST().ShowGraph();
            }
            return(stb);
        }
        STb <FuncDecl, Expr, Sort> GenerateDecoder()
        {
            var ctx = _automataCtx.Z3;

            Expr inputVar    = _automataCtx.MkVar(0, ctx.BoolSort);
            Expr registerVar = _automataCtx.MkVar(1, _automataCtx.MkTupleSort());
            Sort outputSort  = ctx.MkBitVecSort(8);
            var  stb         = new STb <FuncDecl, Expr, Sort>(_automataCtx, DeclarationType.Name, inputVar.Sort, outputSort, registerVar.Sort, _automataCtx.MkTuple(), 0);

            int nextState = 0;
            var states    = new Dictionary <HuffmanDecision, int>();

            PreOrder(_tree, node =>
            {
                var decision = node as HuffmanDecision;
                if (decision != null)
                {
                    states.Add(decision, nextState++);
                }
            });
            Func <HuffmanNode, BaseRule <Expr> > getBaseRule = node =>
            {
                var decision = node as HuffmanDecision;
                if (decision != null)
                {
                    return(new BaseRule <Expr>(Sequence <Expr> .Empty, registerVar, states[decision]));
                }
                else
                {
                    var leaf = (HuffmanLeaf)node;
                    return(new BaseRule <Expr>(new Sequence <Expr>(ctx.MkBV(leaf.Symbol, 8)), registerVar, 0));
                }
            };

            PreOrder(_tree, node =>
            {
                var decision = node as HuffmanDecision;
                if (decision != null)
                {
                    stb.AssignRule(states[decision], new IteRule <Expr>(inputVar, getBaseRule(decision.Left), getBaseRule(decision.Right)));
                    stb.AssignFinalRule(states[decision], new BaseRule <Expr>(Sequence <Expr> .Empty, registerVar, states[decision]));
                }
            });

            if (ShowGraphStages.Count > 0)
            {
                stb.ToST().ShowGraph();
            }
            return(stb);
        }
Exemple #4
0
        // Flatten the register structure
        public static STb <FuncDecl, Expr, Sort> Flatten(this STb <FuncDecl, Expr, Sort> stb)
        {
            var boolDummy = new STb <FuncDecl, Expr, Sort>(stb.Solver, "BoolDummy", stb.OutputSort, stb.OutputSort, stb.Solver.BoolSort, stb.Solver.True, 0);

            boolDummy.AssignRule(0, new BaseRule <Expr>(new Sequence <Expr>(boolDummy.InputVar), boolDummy.RegVar, 0));
            boolDummy.AssignFinalRule(0, new BaseRule <Expr>(Sequence <Expr> .Empty, boolDummy.RegVar, 0));

            var composed = stb.Compose(boolDummy); // Compose with the "dummy" to ensure there is something to eliminate

            composed.Name = stb.Name;
            var explored = composed.ExploreBools(); // Explore bools will flatten when there is something to eliminate

            return(explored);

            // TODO: implement in a less round about way
        }
        STb <FuncDecl, Expr, Sort> GenerateToBooleans()
        {
            var ctx = _automataCtx.Z3;

            Expr inputVar    = _automataCtx.MkVar(0, ctx.MkBitVecSort(8));
            Expr registerVar = _automataCtx.MkVar(1, _automataCtx.MkTupleSort());
            Sort outputSort  = ctx.BoolSort;
            var  stb         = new STb <FuncDecl, Expr, Sort>(_automataCtx, DeclarationType.Name, inputVar.Sort, outputSort, registerVar.Sort, _automataCtx.MkTuple(), 0);

            var bitExprs = new Expr[8];

            for (uint i = 0; i < bitExprs.Length; ++i)
            {
                bitExprs[i] = ctx.MkEq(ctx.MkExtract(i, i, (BitVecExpr)inputVar), ctx.MkBV(1, 1));
            }
            stb.AssignRule(0, new BaseRule <Expr>(new Sequence <Expr>(bitExprs), registerVar, 0));
            stb.AssignFinalRule(0, new BaseRule <Expr>(Sequence <Expr> .Empty, registerVar, 0));
            return(stb);
        }
        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);
        }
Exemple #7
0
        STb <F, T, S> Automaton2STb(Automaton <Pair <BDD, T> > aut, string name, S regSort, T initReg, bool isLoop)
        {
            if (isLoop)
            {
                if (aut.HasMoreThanOneFinalState || aut.GetMovesCountFrom(aut.FinalState) > 0)
                {
                    throw new AutomataException(AutomataExceptionKind.FinalStateMustBeSink);
                }
            }

            var stb = new STb <F, T, S>(solver, name, solver.CharSort, regSort, regSort, initReg, aut.InitialState);

            Func <int, int> getState = (p) =>
            {
                if (isLoop && aut.IsFinalState(p))
                {
                    return(aut.InitialState);
                }
                else
                {
                    return(p);
                }
            };

            Func <int, Sequence <T> > getYield = (p) =>
            {
                if (isLoop && aut.IsFinalState(p))
                {
                    return(Sequence <T> .Empty.Append(solver.MkVar(1, regSort)));
                }
                else
                {
                    return(Sequence <T> .Empty);
                }
            };

            Func <int, T, T> getUpdate = (p, u) =>
            {
                if (isLoop && aut.IsFinalState(p))
                {
                    return(initReg);
                }
                else
                {
                    return(u);
                }
            };

            if (isLoop)
            {
                foreach (var q in aut.States)
                {
                    if (!aut.IsFinalState(q))
                    {
                        stb.AssignRule(q, MkSTbRule(aut.GetMovesFrom(q), getState, getYield, getUpdate));
                    }
                }
                stb.AssignFinalRule(aut.InitialState, new BaseRule <T>(Sequence <T> .Empty, solver.UnitConst, aut.InitialState));
            }
            else
            {
                foreach (var q in aut.States)
                {
                    stb.AssignRule(q, MkSTbRule(aut.GetMovesFrom(q), getState, getYield, getUpdate));
                }

                foreach (var f in aut.GetFinalStates())
                {
                    stb.AssignFinalRule(f, new BaseRule <T>(Sequence <T> .Empty.Append(solver.MkVar(1, regSort)), solver.UnitConst, f));
                }
            }

            return(stb);
        }
Exemple #8
0
        public STb <F, T, S> Mk(string regex, params Tuple <string, STb <F, T, S> >[] args)
        {
            var  K = args.Length;
            bool isLoop;
            var  patternAutomataPairs = solver.CharSetProvider.ConvertCaptures(regex, out isLoop);
            var  captureAutomata      = new Dictionary <string, Automaton <BDD> >();
            var  stbs = new Dictionary <string, STb <F, T, S> >();

            foreach (var arg in args)
            {
                if (stbs.ContainsKey(arg.Item1) || string.IsNullOrEmpty(arg.Item1))
                {
                    throw new AutomataException(AutomataExceptionKind.InvalidArguments);
                }
                stbs[arg.Item1] = arg.Item2;
            }
            foreach (var pair in patternAutomataPairs)
            {
                if (pair.Item1 != "")
                {
                    captureAutomata[pair.Item1] = pair.Item2;
                }
            }

            var captureSortPos  = new Dictionary <string, int>();
            var captureSortName = new Dictionary <string, string>();

            for (int i = 0; i < args.Length; i += 1)
            {
                captureSortName[args[i].Item1] = args[i].Item2.OutputSort.ToString();
                captureSortPos[args[i].Item1]  = i;
            }

            if (Array.Exists(patternAutomataPairs, pair => (pair.Item1 != "" && !captureSortName.ContainsKey(pair.Item1))))
            {
                throw new AutomataException(AutomataExceptionKind.InvalidArguments);
            }

            S[] argSorts = new S[K];
            for (int i = 0; i < K; i++)
            {
                if (!captureAutomata.ContainsKey(args[i].Item1))
                {
                    throw new AutomataException(AutomataExceptionKind.InvalidArguments);
                }
                if (!args[i].Item2.OutputSort.Equals(args[i].Item2.RegisterSort))
                {
                    throw new AutomataException(AutomataExceptionKind.InvalidArguments);
                }
                argSorts[i] = args[i].Item2.OutputSort;
            }

            var regSort = solver.MkTupleSort(argSorts);
            var regVar  = solver.MkVar(1, regSort);
            var initReg = solver.MainSolver.FindOneMember(solver.MkEq(regVar, regVar)).Value;
            var inpVar  = solver.MkVar(0, solver.CharSort);

            var stb = new STb <F, T, S>(solver, "stb", solver.CharSort, regSort, regSort, initReg, 0);

            var nextStateId = 0;
            var stateIdMap  = new Dictionary <Tuple <int, int, int>, int>();
            Func <int, int, int, int> MkState = (n, q1, q2) =>
            {
                int p;
                var nq = new Tuple <int, int, int>(n, q1, q2);
                if (stateIdMap.TryGetValue(nq, out p))
                {
                    return(p);
                }
                else
                {
                    p              = nextStateId;
                    nextStateId   += 1;
                    stateIdMap[nq] = p;
                    return(p);
                }
            };

            var resSTB = new STb <F, T, S>(solver, "STB", solver.CharSort, solver.CharSort, solver.UnitSort, solver.UnitConst, 0);

            resSTB.AssignRule(0, new BaseRule <T>(new Sequence <T>(solver.MkCharVar(0)), solver.UnitConst, 0));
            resSTB.AssignFinalRule(0, new BaseRule <T>(Sequence <T> .Empty, solver.UnitConst, 0));

            for (int i = 0; i < patternAutomataPairs.Length; i++)
            {
                var aut = patternAutomataPairs[i].Item2;

                if (patternAutomataPairs[i].Item1 == "")
                {
                    var autSTMoves = new List <Move <Rule <T> > >();
                    foreach (var move in aut.GetMoves())
                    {
                        //move cannot be epsilon here
                        var cond = solver.ConvertFromCharSet(move.Label);
                        autSTMoves.Add(Move <Rule <T> > .Create(move.SourceState, move.TargetState, Rule <T> .Mk(cond, solver.UnitConst)));
                    }
                    foreach (var f in aut.GetFinalStates())
                    {
                        //collect guards of all moves exitingfrom f
                        var allGuardsFromF = solver.CharSetProvider.False;
                        foreach (var fmove in aut.GetMovesFrom(f))
                        {
                            allGuardsFromF = solver.CharSetProvider.MkOr(allGuardsFromF, fmove.Label);
                        }
                        var elseFromF = solver.ConvertFromCharSet(solver.CharSetProvider.MkNot(allGuardsFromF));
                        autSTMoves.Add(Move <Rule <T> > .Create(f, f, Rule <T> .Mk(elseFromF, solver.UnitConst, solver.MkCharVar(0))));
                        autSTMoves.Add(Move <Rule <T> > .Create(f, f, Rule <T> .MkFinal(solver.True)));
                    }

                    var autST = ST <F, T, S> .Create(solver, patternAutomataPairs[i].Item1, solver.UnitConst, solver.CharSort,
                                                     solver.CharSort, solver.UnitSort, aut.InitialState, autSTMoves);

                    var autSTb = autST.ToSTb();
                    resSTB = resSTB.Compose(autSTb);
                }
                else
                {
                    var stb1 = stbs[patternAutomataPairs[i].Item1];
                    if (!stb1.InputSort.Equals(solver.CharSort))
                    {
                        throw new AutomataException(AutomataExceptionKind.InvalidArguments);
                    }

                    var autSTMoves = new List <Move <Rule <T> > >();
                    foreach (var move in aut.GetMoves())
                    {
                        //move cannot be epsilon here
                        var cond = solver.ConvertFromCharSet(move.Label);
                        autSTMoves.Add(Move <Rule <T> > .Create(move.SourceState, move.TargetState, Rule <T> .Mk(cond, solver.UnitConst, inpVar)));
                    }
                    foreach (var f in aut.GetFinalStates())
                    {
                        autSTMoves.Add(Move <Rule <T> > .Create(f, f, Rule <T> .MkFinal(solver.True)));
                    }

                    var autST = ST <F, T, S> .Create(solver, patternAutomataPairs[i].Item1, solver.UnitConst, solver.CharSort,
                                                     solver.CharSort, solver.UnitSort, aut.InitialState, autSTMoves);

                    var autSTb = autST.ToSTb();

                    var stb2 = autSTb.Compose(stb1);

                    foreach (var f in stb.States)
                    {
                        var frule = stb.GetFinalRuleFrom(f);
                        if (frule.IsNotUndef)
                        {
                            //var frule1 =
                        }
                    }
                }
            }

            throw new NotImplementedException();
        }
        public STb <FUNC, TERM, SORT> Minimize()
        {
            var s = stb.Solver;

            var alphaSort = s.MkOptionSort(stb.InputSort);
            var autoSort  = s.MkTupleSort(alphaSort, stb.OutputListSort, stb.RegisterSort, stb.RegisterSort);
            var autoVar   = s.MkVar(3, autoSort);

            var autoInput      = s.MkProj(0, autoVar);
            var autoSomeInput  = s.MkGetSomeValue(autoInput);
            var autoOutputList = s.MkProj(1, autoVar);
            var autoOldReg     = s.MkProj(2, autoVar);
            var autoNewReg     = s.MkProj(3, autoVar);

            Func <TERM, TERM> finalSubstitute    = (t) => s.ApplySubstitution(t, stb.RegVar, autoOldReg);
            Func <TERM, TERM> nonFinalSubstitute = (t) => finalSubstitute(s.ApplySubstitution(t, stb.InputVar, autoSomeInput));

            int acceptingState = stb.States.Max() + 1;
            int errorState     = stb.States.Max() + 2;
            var moves          = new List <Move <TERM> >();

            foreach (var state in stb.States)
            {
                var nonFinalConds = new List <TERM>();
                foreach (var nonFinal in st.GetNonFinalMovesFrom(state))
                {
                    var rule  = nonFinal.Label;
                    var conds = new List <TERM>();
                    conds.Add(s.MkIsSome(autoInput));
                    conds.Add(nonFinalSubstitute(rule.Guard));
                    var outputList = autoOutputList;
                    foreach (var yield in rule.Output)
                    {
                        conds.Add(s.MkIsCons(outputList));
                        conds.Add(s.MkEq(s.MkFirstOfList(outputList), nonFinalSubstitute(yield)));
                        outputList = s.MkRestOfList(outputList);
                    }
                    conds.Add(s.MkIsNil(outputList));
                    conds.Add(s.MkEq(autoNewReg, nonFinalSubstitute(rule.Update)));
                    var cond = s.MkAnd(conds);
                    moves.Add(Move <TERM> .Create(state, nonFinal.TargetState, cond));
                    nonFinalConds.Add(cond);
                }
                var finalConds = new List <TERM>();
                foreach (var rule in st.GetFinalRules(state))
                {
                    var conds = new List <TERM>();
                    conds.Add(s.MkIsNone(autoInput));
                    conds.Add(finalSubstitute(rule.Guard));
                    var outputList = autoOutputList;
                    foreach (var yield in rule.Output)
                    {
                        conds.Add(s.MkIsCons(outputList));
                        conds.Add(s.MkEq(s.MkFirstOfList(outputList), finalSubstitute(yield)));
                        outputList = s.MkRestOfList(outputList);
                    }
                    conds.Add(s.MkIsNil(outputList));
                    var cond = s.MkAnd(conds);
                    moves.Add(Move <TERM> .Create(state, acceptingState, cond));
                    finalConds.Add(cond);
                }
            }
            //moves.Add(Move<TERM>.Create(errorState, errorState, s.True));
            var auto = Automaton <TERM> .Create(stb.Solver, stb.InitialState, new int[] { acceptingState }, moves);

            auto.CheckDeterminism(stb.Solver);
            var blocks = auto.BookkeepingMinimize(stb.Solver);

            Func <STbRule <TERM>, STbRule <TERM> > redirect = null;

            redirect = r =>
            {
                switch (r.RuleKind)
                {
                case STbRuleKind.Undef:
                    return(r);

                case STbRuleKind.Base:
                    return(new BaseRule <TERM>(r.Yields, r.Register, blocks[r.State].GetRepresentative()));

                case STbRuleKind.Ite:
                    var t = redirect(r.TrueCase);
                    var f = redirect(r.FalseCase);
                    return(new IteRule <TERM>(r.Condition, t, f));

                default:
                    throw new NotImplementedException();
                }
            };

            var minimized = new STb <FUNC, TERM, SORT>(stb.Solver, stb.Name + "_min", stb.InputSort, stb.OutputSort, stb.RegisterSort, stb.InitialRegister,
                                                       blocks[stb.InitialState].GetRepresentative());
            var representatives = new HashSet <int>();

            foreach (var state in stb.States)
            {
                representatives.Add(blocks[state].GetRepresentative());
            }
            foreach (var state in representatives)
            {
                minimized.AssignRule(state, redirect(stb.GetRuleFrom(state)).CollapseRedundantITEs(s));
                minimized.AssignFinalRule(state, redirect(stb.GetFinalRuleFrom(state)).CollapseRedundantITEs(s));
            }
            return(minimized);
        }
Exemple #10
0
        public STb <FUNC, TERM, SORT> Compose()
        {
            var stack         = new SimpleStack <Tuple <int, int> >();
            int stateId       = 1;
            var stateIdMap    = new Dictionary <Tuple <int, int>, int>();
            var revStateIdMap = new Dictionary <int, Tuple <int, int> >();
            var q0A_x_q0B     = new Tuple <int, int>(A.InitialState, B.InitialState);

            stack.Push(q0A_x_q0B);
            stateIdMap[q0A_x_q0B] = 0;
            revStateIdMap[0]      = q0A_x_q0B;

            Func <int, int, int> ComposeStates = (x, y) =>
            {
                var xy = new Tuple <int, int>(x, y);
                int q;
                if (stateIdMap.TryGetValue(xy, out q))
                {
                    return(q);
                }
                else
                {
                    q                = stateId;
                    stateId         += 1;
                    stateIdMap[xy]   = q;
                    revStateIdMap[q] = xy;
                    stack.Push(xy);
                    return(q);
                }
            };
            var A2B = new STb <FUNC, TERM, SORT>(solver, A.Name + "2" + B.Name, A.InputSort, B.OutputSort, regSort, JoinRegs(A.InitialRegister, B.InitialRegister), 0);

            //create normal composed rules
            while (stack.IsNonempty)
            {
                var qA_x_qB = stack.Pop();
                var qA      = qA_x_qB.Item1;
                var qB      = qA_x_qB.Item2;
                var ruleA   = A.GetRuleFrom(qA);
                if (ruleA.IsNotUndef)
                {
                    var qAB_rule = Comp(solver.True, ruleA, qB, ComposeStates, false);
                    A2B.AssignRule(stateIdMap[qA_x_qB], qAB_rule);
                }
                else
                {
                    A2B.AssignRule(stateIdMap[qA_x_qB], UndefRule <TERM> .Default);
                }
            }
            foreach (var qAB in A2B.States)
            {
                var qA_x_qB = revStateIdMap[qAB];
                var qA      = qA_x_qB.Item1;
                var qB      = qA_x_qB.Item2;
                var ruleA   = A.GetFinalRuleFrom(qA);
                if (ruleA.IsNotUndef)
                {
                    var qAB_Frule = Comp(solver.True, ruleA, qB, (p, q) => qAB, true);
                    A2B.AssignFinalRule(qAB, qAB_Frule);
                }
            }

            A2B.EliminateDeadends();


            //Func<Rule<TERM>, Rule<TERM>> ReplaceWithEpsilon = (r) =>
            //    {

            //    };

            //var aut = A2B.ToST(true).automaton.RelpaceAllGuards(ReplaceWithEpsilon);


            return(A2B);
        }
Exemple #11
0
        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);
        }
        STb <FuncDecl, Expr, Sort> GenerateSTb()
        {
            var name = DeclarationType.ContainingNamespace.Name + "." +
                       (DeclarationType.ContainingType == null ? "" : DeclarationType.ContainingType.Name + ".") + DeclarationType.Name;

            Console.WriteLine("Exploring " + name);

            Expr    inputVar    = _info.AutomataCtx.MkVar(0, Mapper.GetSortMapping(_transducerType.TypeArguments[0]).Sort);
            Expr    registerVar = _info.AutomataCtx.MkVar(1, Mapper.GetSortMapping(DeclarationType).Sort);
            Mutator register    = Mapper.GetSortMapping(DeclarationType).MutatorForValue(registerVar);

            var methods = DeclarationType.DeclaringSyntaxReferences.Select(r => r.GetSyntax())
                          .SelectMany(s => s.DescendantNodes(n => !(n is MethodDeclarationSyntax)))
                          .OfType <MethodDeclarationSyntax>().Select(Syntax => new { Syntax, Symbol = Model.GetDeclaredSymbol(Syntax) as IMethodSymbol })
                          .Where(x => x.Symbol != null);

            // Find the Update function
            var updateMethods = methods.Where(x => x.Symbol.MetadataName == "Update" && x.Symbol.IsOverride &&
                                              x.Symbol.Parameters.Length == 1 && x.Symbol.Parameters[0].Type == InputTypeSymbol).ToArray();

            if (updateMethods.Length == 0)
            {
                throw new SyntaxErrorException("No IEnumerable<" + OutputTypeSymbol + "> Update(" + InputTypeSymbol + ") method declared");
            }
            else if (updateMethods.Length > 1)
            {
                throw new SyntaxErrorException("Multiple Update methods declared");
            }
            var updateMethod = updateMethods[0];
            // Explore the Update function
            var updateCfg = new ControlFlowGraph(updateMethod.Syntax.Body, Model);
            Dictionary <ISymbol, Mutator> parameters = updateMethod.Symbol.Parameters
                                                       .ToDictionary(p => (ISymbol)p, p => Mapper.GetSortMapping(_transducerType.TypeArguments[0]).MutatorForValue(inputVar));
            var updateEntryState = new MainExplorationState(_info, updateCfg.EntryPoint, register, parameters, new[] { inputVar, registerVar });
            var updateRule       = updateEntryState.Explore();

            // Find the Finish function
            var finishMethods = methods.Where(x => x.Symbol.MetadataName == "Finish" && x.Symbol.IsOverride &&
                                              x.Symbol.Parameters.Length == 0).ToArray();
            STbRule <Expr> finishRule;

            if (finishMethods.Length == 0)
            {
                finishRule = new BaseRule <Expr>(Sequence <Expr> .Empty, register.CreateUpdate(), 0);
            }
            else
            {
                if (finishMethods.Length > 1)
                {
                    throw new SyntaxErrorException("Multiple Finish methods declared");
                }
                var finishMethod = finishMethods[0];
                // Explore the Finish function
                var finishCfg        = new ControlFlowGraph(finishMethod.Syntax.Body, Model);
                var finishEntryState = new MainExplorationState(_info, finishCfg.EntryPoint, register, new Dictionary <ISymbol, Mutator>(), new[] { registerVar });
                finishRule = finishEntryState.Explore();
            }

            var outputSort = Mapper.GetSortMapping(_transducerType.TypeArguments[1]).Sort;
            var stb        = new STb <FuncDecl, Expr, Sort>(_info.AutomataCtx, DeclarationType.Name, inputVar.Sort, outputSort, registerVar.Sort,
                                                            Mapper.GetSortMapping(DeclarationType).MutatorForDefaultValue().CreateUpdate().SafeSimplify(Ctx), 0);

            stb.AssignRule(0, updateRule);
            stb.AssignFinalRule(0, finishRule);

            if (ShowGraphStages.Contains(ShowGraph.Stage.UnSimplified))
            {
                stb.ShowGraph();
            }
            stb = stb.Flatten();
            if (ShowGraphStages.Contains(ShowGraph.Stage.Simplified))
            {
                stb.ToST().ShowGraph();
            }
            return(stb);
        }