Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
            }
        }