Example #1
0
        internal static bool WantsAutoTriggers(QuantifierExpr quantifier)
        {
            Contract.Requires(quantifier.SplitQuantifier == null); // Don't call this on a quantifier with a Split clause: it's not a real quantifier
            bool wantsAutoTriggers = true;

            return(!Attributes.ContainsBool(quantifier.Attributes, "autotriggers", ref wantsAutoTriggers) || wantsAutoTriggers);
        }
        // need to push bound type variables
        public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
        {
            if (!(node is ForallExpr || node is ExistsExpr))
            {
                throw new ProofGenUnexpectedStateException(GetType(), "can only handle forall and exists quantifiers");
            }

            //Quantifers with multiple bound variables are desugared into multiple quantifiers expressions with single variables
            foreach (var boundTyVar in node.TypeParameters)
            {
                tyVarTranslation.AddBoundVariable(boundTyVar);
            }

            var numTyVarBefore = tyVarTranslation.NumBoundVariables();

            Visit(node.Body);

            if (numTyVarBefore != tyVarTranslation.NumBoundVariables())
            {
                throw new ProofGenUnexpectedStateException(GetType(),
                                                           "quantifier levels not the same before and after");
            }

            for (var i = node.TypeParameters.Count - 1; i >= 0; i--)
            {
                tyVarTranslation.DropLastBoundVariable();
            }

            return(node);
        }
Example #3
0
        private static bool ShallowEq(QuantifierExpr expr1, QuantifierExpr expr2)
        {
            if (!TriggerUtils.SameNullity(expr1.SplitQuantifier, expr2.SplitQuantifier))
            {
                return(false);
            }

            if (expr1.SplitQuantifier != null && expr2.SplitQuantifier != null)
            {
                return(ShallowEq_Top(expr1.SplitQuantifierExpression, expr2.SplitQuantifierExpression));
            }

            if (expr1.TypeArgs.Count != expr2.TypeArgs.Count ||
                !TriggerUtils.SameNullity(expr1.Range, expr2.Range))
            {
                return(false);
            }

            if (expr1 is ExistsExpr && expr2 is ExistsExpr)
            {
                return(ShallowEq((ExistsExpr)expr1, (ExistsExpr)expr2));
            }
            else if (expr1 is ForallExpr && expr2 is ForallExpr)
            {
                return(ShallowEq((ForallExpr)expr1, (ForallExpr)expr2));
            }
            else
            {
                return(false);
            }
        }
        private static bool AllowsSplitting(QuantifierExpr quantifier)
        {
            // allow split if attributes doesn't contains "split" or it is "split: true" and it is not an empty QuantifierExpr (boundvar.count>0)
            bool splitAttr = true;

            return((!Attributes.ContainsBool(quantifier.Attributes, "split", ref splitAttr) || splitAttr) && (quantifier.BoundVars.Count > 0));
        }
Example #5
0
        internal IEnumerable <TriggerMatch> LoopingSubterms(QuantifierExpr quantifier)
        {
            Contract.Requires(quantifier.SplitQuantifier == null); // Don't call this on a quantifier with a Split clause: it's not a real quantifier
            var matchingSubterms = this.MatchingSubterms(quantifier);
            var boundVars        = new HashSet <BoundVar>(quantifier.BoundVars);

            return(matchingSubterms.Where(tm => tm.CouldCauseLoops(Terms, boundVars)));
        }
Example #6
0
 private bool IsForall(QuantifierExpr quantifierExpr)
 {
     if (quantifierExpr is ForallExpr)
     {
         return(true);
     }
     if (quantifierExpr is ExistsExpr)
     {
         return(false);
     }
     throw new ProofGenUnexpectedStateException(GetType(), "Unexpected quantifier");
 }
Example #7
0
        // This is necessary because the root of the Tree might be a QuantifierExpr
        public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
        {
            bool goDeeper = CountExpr(node);

            if (goDeeper)
            {
                return(base.VisitQuantifierExpr(node));
            }
            else
            {
                return(node);
            }
        }
        public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
        {
            if (node.TypeParameters.Count > 0)
            {
                _result = true;
                _hasTypeQuantification = true;
            }

            _withinNumQuantifier++;
            Visit(node._Body);
            _withinNumQuantifier--;

            return(node);
        }
Example #9
0
        public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
        {
            var oldE = existentialExpr;

            if (node is ExistsExpr)
            {
                existentialExpr = (node as ExistsExpr);
            }

            node = base.VisitQuantifierExpr(node);

            existentialExpr = oldE;
            return(node);
        }
        internal static IEnumerable <Expression> SplitQuantifier(QuantifierExpr quantifier)
        {
            var body   = quantifier.Term;
            var binary = body as BinaryExpr;

            if (quantifier is ForallExpr)
            {
                IEnumerable <Expression> stream;
                if (binary != null && (binary.Op == BinaryExpr.Opcode.Imp || binary.Op == BinaryExpr.Opcode.Or))
                {
                    stream = SplitAndStich(binary, BinaryExpr.Opcode.And);
                }
                else
                {
                    stream = SplitExpr(body, BinaryExpr.Opcode.And);
                }
                foreach (var e in stream)
                {
                    var tok = new NestedToken(quantifier.tok, e.tok);
                    yield return(new ForallExpr(tok, quantifier.TypeArgs, quantifier.BoundVars, quantifier.Range, e, CopyAttributes(quantifier.Attributes))
                    {
                        Type = quantifier.Type
                    });
                }
            }
            else if (quantifier is ExistsExpr)
            {
                IEnumerable <Expression> stream;
                if (binary != null && binary.Op == BinaryExpr.Opcode.And)
                {
                    stream = SplitAndStich(binary, BinaryExpr.Opcode.Or);
                }
                else
                {
                    stream = SplitExpr(body, BinaryExpr.Opcode.Or);
                }
                foreach (var e in stream)
                {
                    var tok = new NestedToken(quantifier.tok, e.tok);
                    yield return(new ExistsExpr(tok, quantifier.TypeArgs, quantifier.BoundVars, quantifier.Range, e, CopyAttributes(quantifier.Attributes))
                    {
                        Type = quantifier.Type
                    });
                }
            }
            else
            {
                yield return(quantifier);
            }
        }
Example #11
0
        // Do not dualise quantified variables
        public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
        {
            List <Variable> vs = node.Dummies;

            foreach (Variable dummy in vs)
            {
                quantifiedVars.Add(dummy);
            }
            base.VisitQuantifierExpr(node);
            foreach (Variable dummy in vs)
            {
                quantifiedVars.Remove(dummy);
            }
            return(node);
        }
Example #12
0
        public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
        {
            if (!(node is ForallExpr || node is ExistsExpr))
            {
                throw new ProofGenUnexpectedStateException(GetType(), "can only handle forall and exists quantifiers");
            }

            var isForall = IsForall(node);

            //Quantifers with multiple bound variables are desugared into multiple quantifiers expressions with single variables
            foreach (var boundVar in node.Dummies)
            {
                boogieVarTranslation.VarTranslation.AddBoundVariable(boundVar);
            }
            foreach (var boundTyVar in node.TypeParameters)
            {
                boogieVarTranslation.TypeVarTranslation.AddBoundVariable(boundTyVar);
            }

            var numValVarBefore = boogieVarTranslation.VarTranslation.NumBoundVariables();
            var numTyVarBefore  = boogieVarTranslation.TypeVarTranslation.NumBoundVariables();

            var result = Translate(node.Body);

            if (numValVarBefore != boogieVarTranslation.VarTranslation.NumBoundVariables() ||
                numTyVarBefore != boogieVarTranslation.TypeVarTranslation.NumBoundVariables())
            {
                throw new ProofGenUnexpectedStateException(GetType(),
                                                           "quantifier levels not the same before and after");
            }

            for (var i = node.Dummies.Count - 1; i >= 0; i--)
            {
                boogieVarTranslation.VarTranslation.DropLastBoundVariable();
                var boundVar     = node.Dummies[i];
                var boundVarType = typeIsaVisitor.Translate(boundVar.TypedIdent.Type);
                result = IsaBoogieTerm.Quantifier(isForall, boundVarType, result);
            }

            for (var i = node.TypeParameters.Count - 1; i >= 0; i--)
            {
                boogieVarTranslation.TypeVarTranslation.DropLastBoundVariable();
                result = IsaBoogieTerm.TypeQuantifier(isForall, result);
            }

            ReturnResult(result);
            return(node);
        }
Example #13
0
        ////////////////////////////////////////////////////////////////////////////////////
        //TODO:Check if we get functions here
        private Term makeExpression(QuantifierExpr qe, bool old)
        {
            Term e = null;

            {
                List <Logic.Variable> quantifiedVariables = new List <Logic.Variable>();
                foreach (Microsoft.Boogie.Variable bv in qe.Dummies)
                {
                    quantifiedVariables.Add(new Logic.Basic.Variable(bv.TypedIdent.Name));
                }
                foreach (var v in quantifiedVariables)
                {
                    boundVariables.Add(v.name, v);
                }
                e = makeExpression(qe.Body, old);
                foreach (var v in quantifiedVariables)
                {
                    boundVariables.Remove(v.name);
                }
            }


            {
                Logic.Quantifier q = makeQuantifier(qe.Kind);
                for (int i = qe.Dummies.Length - 1; i >= 0; i--)
                {
                    Microsoft.Boogie.Variable v = qe.Dummies[i];
                    Logic.Sort     ls           = new Logic.Boogie.BoogieSort(v.TypedIdent.Type);
                    Logic.Variable lv           = new Logic.Boogie.BoogieVariable(v);
                    e = new Boogie.QuantifiedExpression(qe, q, lv, ls, e);
                }
            }
            {
                Logic.TypeQuantifier tq = makeTypeQuantifier(qe.Kind);
                for (int i = qe.TypeParameters.Length - 1; i >= 0; i--)
                {
                    Microsoft.Boogie.TypeVariable btv = qe.TypeParameters[i];
                    Logic.TypeVariable            tv  = new Logic.Boogie.TypeVariable(btv);
                    e = new Boogie.QuantifiedTypeExpression(qe, tq, tv, e);
                }
            }
            return(e);
        }
Example #14
0
 ///////////////////////////////////////////////////////////
 public BoogieQuantifiedTypeExpression(
     QuantifierExpr boogieExpression,
     TypeQuantifier quantifier,
     TypeVariable variable,
     Expression expression,
     List <Expression> triggers,
     string attributes
     )
     :
     base(
         quantifier,
         variable,
         expression,
         triggers,
         attributes
         )
 {
     Debug.Assert(boogieExpression != null);
     boogieQTExpression = boogieExpression;
 }
 ///////////////////////////////////////////////////////////
 public BoogieQuantifiedExpression(
     Scope s,
     QuantifierExpr boogieExpression,
     Quantifier quantifier,
     BoundVariable variable,
     Expression expression,
     IEnumerable <IEnumerable <Expression> > triggers,
     string attributes
     )
     : base(
         s,
         quantifier,
         variable,
         expression,
         triggers,
         attributes
         )
 {
     Debug.Assert(boogieExpression != null);
     boogieQExpression = boogieExpression;
 }
Example #16
0
 bool RewriteMatchingLoop()
 {
     if (expr is QuantifierExpr && TriggerUtils.WantsMatchingLoopRewrite((QuantifierExpr)expr))
     {
         QuantifierExpr quantifier = (QuantifierExpr)expr;
         var            l          = new List <QuantifierWithTriggers>();
         // only split quantifier expr now.
         List <Expression> splits = new List <Expression>();
         foreach (var q in quantifiers)
         {
             var matchingLoopRewriter = new MatchingLoopRewriter();
             var qq = matchingLoopRewriter.RewriteMatchingLoops(q);
             splits.Add(qq);
             l.Add(new QuantifierWithTriggers(qq));
         }
         quantifier.SplitQuantifier = splits;
         quantifiers = l;
         return(true);
     }
     return(false);
 }
Example #17
0
 bool RewriteMatchingLoop()
 {
     if (expr is QuantifierExpr)
     {
         QuantifierExpr    quantifier = (QuantifierExpr)expr;
         var               l          = new List <QuantifierWithTriggers>();
         List <Expression> splits     = new List <Expression>();
         bool              rewritten  = false;
         foreach (var q in quantifiers)
         {
             if (TriggerUtils.NeedsAutoTriggers(q.quantifier) && TriggerUtils.WantsMatchingLoopRewrite(q.quantifier))
             {
                 var matchingLoopRewriter = new MatchingLoopRewriter();
                 var qq = matchingLoopRewriter.RewriteMatchingLoops(q);
                 splits.Add(qq);
                 l.Add(new QuantifierWithTriggers(qq));
                 rewritten = true;
             }
             else
             {
                 // don't rewrite the quantifier if we are not auto generate triggers.
                 // This is because rewriting introduces new boundvars and will cause
                 // user provided triggers not mention all boundvars
                 splits.Add(q.quantifier);
                 l.Add(q);
             }
         }
         if (rewritten)
         {
             quantifier.SplitQuantifier = splits;
             quantifiers = l;
             return(true);
         }
     }
     return(false);
 }
 internal static IEnumerable <TriggerMatch> SubexpressionsMatchingTrigger(this QuantifierExpr quantifier, Expression trigger)
 {
     return(quantifier.AllSubExpressions(true, true)
            .Select(e => TriggerUtils.PrepareExprForInclusionInTrigger(e).MatchAgainst(trigger, quantifier.BoundVars, e))
            .Where(e => e.HasValue).Select(e => e.Value));
 }
Example #19
0
        List <Expression> GenerateAutoReqs(Expression expr, Function parent)
        {
            List <Expression> reqs = new List <Expression>();
            Func <Expression, List <Expression> > generateAutoReqs = e => GenerateAutoReqs(e, parent);

            if (expr is LiteralExpr)
            {
            }
            else if (expr is ThisExpr)
            {
            }
            else if (expr is IdentifierExpr)
            {
            }
            else if (expr is SeqDisplayExpr)
            {
                SeqDisplayExpr e = (SeqDisplayExpr)expr;
                foreach (var elt in e.Elements)
                {
                    reqs.AddRange(generateAutoReqs(elt));
                }
            }
            else if (expr is FieldSelectExpr)
            {
                FieldSelectExpr e = (FieldSelectExpr)expr;
                reqs.AddRange(generateAutoReqs(e.Obj));
            }
            else if (expr is SeqSelectExpr)
            {
                SeqSelectExpr e = (SeqSelectExpr)expr;
                reqs.AddRange(generateAutoReqs(e.Seq));
                if (e.E0 != null)
                {
                    reqs.AddRange(generateAutoReqs(e.E0));
                }
                if (e.E1 != null)
                {
                    reqs.AddRange(generateAutoReqs(e.E1));
                }
            }
            else if (expr is SeqUpdateExpr)
            {
                SeqUpdateExpr e = (SeqUpdateExpr)expr;
                reqs.AddRange(generateAutoReqs(e.Seq));
                reqs.AddRange(generateAutoReqs(e.Index));
                reqs.AddRange(generateAutoReqs(e.Value));
            }
            else if (expr is FunctionCallExpr)
            {
                FunctionCallExpr e = (FunctionCallExpr)expr;
                foreach (var arg in e.Args)
                {
                    reqs.AddRange(generateAutoReqs(arg));
                }
                if (parent == null || parent.Name != e.name)
                {
                    ReqFunction(e.Function);
                    reqs.AddRange(GatherReqs(e.Function, e.Args));
                }
            }
            else if (expr is DatatypeValue)
            {
                DatatypeValue dtv = (DatatypeValue)expr;
                for (int i = 0; i < dtv.Arguments.Count; i++)
                {
                    Expression arg = dtv.Arguments[i];
                    reqs.AddRange(generateAutoReqs(arg));
                }
            }
            else if (expr is OldExpr)
            {
            }
            else if (expr is MatchExpr)
            {
                MatchExpr e = (MatchExpr)expr;
                reqs.AddRange(generateAutoReqs(e.Source));
                List <MatchCaseExpr> newMatches = new List <MatchCaseExpr>();
                foreach (MatchCaseExpr caseExpr in e.Cases)
                {
                    MatchCaseExpr c = new MatchCaseExpr(caseExpr.name, caseExpr.Arguments, Andify(generateAutoReqs(caseExpr.Body)));
                    newMatches.Add(c);
                }
                reqs.Add(new MatchExpr(e.Source, newMatches));
            }
            else if (expr is FreshExpr)
            {
            }
            else if (expr is UnaryExpr)
            {
                UnaryExpr  e   = (UnaryExpr)expr;
                Expression arg = e.E;
                reqs.AddRange(generateAutoReqs(arg));
            }
            else if (expr is BinaryExpr)
            {
                BinaryExpr e = (BinaryExpr)expr;
                switch (e.Op)
                {
                case BinaryExpr.Opcode.Imp:
                case BinaryExpr.Opcode.And:
                    reqs.AddRange(generateAutoReqs(e.E0));
                    foreach (var req in generateAutoReqs(e.E1))
                    {
                        reqs.Add(new BinaryExpr(Token.NoToken, BinaryExpr.Opcode.Imp, e.E0, req));
                    }
                    break;

                case BinaryExpr.Opcode.Or:
                    reqs.AddRange(generateAutoReqs(e.E0));
                    foreach (var req in generateAutoReqs(e.E1))
                    {
                        reqs.Add(new BinaryExpr(Token.NoToken, BinaryExpr.Opcode.Imp,
                                                new UnaryExpr(Token.NoToken, UnaryExpr.Opcode.Not, e.E0), req));
                    }
                    break;

                default:
                    reqs.AddRange(generateAutoReqs(e.E0));
                    reqs.AddRange(generateAutoReqs(e.E1));
                    break;
                }
            }
            else if (expr is LetExpr)
            {
                var e = (LetExpr)expr;
                if (e.Exact)
                {
                    foreach (var rhs in e.RHSs)
                    {
                        reqs.AddRange(generateAutoReqs(rhs));
                    }
                    var new_reqs = generateAutoReqs(e.Body);
                    if (new_reqs.Count > 0)
                    {
                        reqs.Add(new LetExpr(e.Exact, e.LHSs, e.RHSs, Andify(new_reqs)));
                    }
                }
            }
            else if (expr is QuantifierExpr)
            {
                QuantifierExpr e         = (QuantifierExpr)expr;
                var            auto_reqs = generateAutoReqs(e.Term);
                if (auto_reqs.Count > 0)
                {
                    Expression allReqsSatisfied        = Andify(auto_reqs);
                    Expression allReqsSatisfiedAndTerm = new BinaryExpr(Token.NoToken, BinaryExpr.Opcode.And, allReqsSatisfied, e.Term);
                    e.Term = allReqsSatisfiedAndTerm;
                }
            }
            else if (expr is StmtExpr)
            {
                var e = (StmtExpr)expr;
                reqs.AddRange(generateAutoReqs(e.E));
            }
            else if (expr is ITEExpr)
            {
                ITEExpr e = (ITEExpr)expr;
                reqs.AddRange(generateAutoReqs(e.Test));
                reqs.Add(new ITEExpr(e.Test, Andify(generateAutoReqs(e.Thn)), Andify(generateAutoReqs(e.Els))));
            }
            return(reqs);
        }
Example #20
0
 private TriggerAnnotation AnnotateQuantifier(QuantifierExpr expr)
 {
     return(AnnotateQuantifierOrLetExpr(expr, expr.BoundVars));
 }
Example #21
0
        private Expr PrintQuantifierExpr(QuantifierExpr QE)
        {
            if (QE is ExistsExpr)
            {
                TW.Write("(exists");
            }
            else if (QE is ForallExpr)
            {
                TW.Write("(forall");
            }
            else
            {
                throw new NotSupportedException("Unsupported quantifier expr");
            }

            PushIndent();
            PrintSeperator();
            TW.Write("(");
            PushIndent();
            PrintSeperator();

            foreach (var boundVar in QE.Dummies)
            {
                PrintSeperator();
                TW.Write("(" + boundVar.Name + " " + GetSMTLIBType(boundVar.TypedIdent.Type) + ")");
            }
            PopIndent();
            PrintSeperator();
            TW.Write(")");
            PrintSeperator();

            // Handle Triggers
            if (QE.Triggers == null || !PrintTriggers)
            {
                PrintExpr(QE.Body);
            }
            else
            {
                TW.Write("(!");
                PushIndent();
                PrintSeperator();

                PrintExpr(QE.Body);
                PrintSeperator();

                // fixme: pos!
                // Print triggers
                var trigger = QE.Triggers;
                if (trigger.Pos)
                {
                    while (trigger != null)
                    {
                        // list of expressions
                        TW.Write(":pattern (");
                        PushIndent();
                        PrintSeperator();
                        foreach (var triggerExpr in trigger.Tr)
                        {
                            PrintExpr(triggerExpr);
                            PrintSeperator();
                        }
                        PopIndent();
                        TW.Write(")");
                        trigger = trigger.Next;
                    }
                }
                else
                {
                    if (trigger.Tr.Count != 1)
                    {
                        throw new InvalidDataException("Negative trigger is malformed");
                    }

                    // no-pattern takes an expression rather than a list of expressions
                    TW.Write(":no-pattern");
                    PushIndent();
                    PrintSeperator();
                    PrintExpr(trigger.Tr[0]);
                    PopIndent();
                }

                PopIndent();
                PrintSeperator();
                TW.Write(")");
            }

            PopIndent();
            PrintSeperator();
            TW.Write(")");
            return(QE);
        }
 internal QuantifierWithTriggers(QuantifierExpr quantifier)
 {
     this.quantifier         = quantifier;
     this.RejectedCandidates = new List <TriggerCandidate>();
 }
Example #23
0
 public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
 {
     add(node);
     return(base.VisitQuantifierExpr(node));
 }
 public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
 {
     FindInstantiationSources(node, "skolem_add_to_pool");
     return(base.VisitQuantifierExpr(node));
 }
Example #25
0
 public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
 {
     return(base.VisitQuantifierExpr((QuantifierExpr)node.Clone()));
 }
Example #26
0
 public override QuantifierExpr VisitQuantifierExpr(QuantifierExpr node)
 {
     node             = base.VisitQuantifierExpr(node);
     quantifiersExist = true;
     return(node);
 }
Example #27
0
    public RtlExp GhostExpressionRec(Expression exp, bool inRecSpec = false, bool inRequiresOrOld = false)
    {
        Util.Assert(!isPrinting);
        exp = GetExp(exp);
        StmtExpr         stmtExpr    = exp as StmtExpr;
        IdentifierExpr   idExp       = exp as IdentifierExpr;
        LiteralExpr      literal     = exp as LiteralExpr;
        BinaryExpr       binary      = exp as BinaryExpr;
        UnaryExpr        unary       = exp as UnaryExpr;
        ITEExpr          ite         = exp as ITEExpr;
        ExistsExpr       existsExp   = exp as ExistsExpr;
        ForallExpr       forallExp   = exp as ForallExpr;
        LetExpr          letExp      = exp as LetExpr;
        MatchExpr        matchExp    = exp as MatchExpr;
        OldExpr          oldExp      = exp as OldExpr;
        FreshExpr        freshExp    = exp as FreshExpr;
        FunctionCallExpr funCall     = exp as FunctionCallExpr;
        DatatypeValue    dataVal     = exp as DatatypeValue;
        FieldSelectExpr  fieldSelect = exp as FieldSelectExpr;
        SeqSelectExpr    seqSelect   = exp as SeqSelectExpr;
        SeqUpdateExpr    seqUpdate   = exp as SeqUpdateExpr;
        SeqDisplayExpr   seqDisplay  = exp as SeqDisplayExpr;

        Func <Expression, RtlExp> G = e => GhostExpression(e, inRecSpec, inRequiresOrOld);

        if (stmtExpr != null)
        {
            if (stmtExprEnabled)
            {
                if (ignoreStmtExpr == 0)
                {
                    AddGhostStatement(stmtExpr.S);
                }
                return(G(stmtExpr.E));
            }
            else
            {
                throw new Exception("not implemented: cannot handle statement expression here");
            }
        }
        else if (idExp != null)
        {
            return(AsVar(idExp));
        }
        else if (literal != null && literal.Value is BigInteger)
        {
            return(new RtlInt((BigInteger)(literal.Value)));
        }
        else if (literal != null && literal.Value is bool)
        {
            return(new RtlLiteral((bool)(literal.Value) ? "true" : "false"));
        }
        else if (literal != null && literal.Value == null)
        {
            return(new RtlLiteral("ArrayOfInt(0 - 1, NO_ABS)"));
        }
        else if (literal != null && literal.Value is Microsoft.Basetypes.BigDec)
        {
            return(new RtlLiteral(((Microsoft.Basetypes.BigDec)literal.Value).ToDecimalString()));
        }
        else if (binary != null)
        {
            string          op              = null;
            string          internalOp      = null;
            CompileFunction compileFunction = this as CompileFunction;
            string          thisFuncName    = (compileFunction == null) ? null : compileFunction.function.Name;
            switch (binary.ResolvedOp)
            {
            case BinaryExpr.ResolvedOpcode.SeqEq:
                return(new RtlApply(dafnySpec.GetSeqOperationName(AppType(binary.E0.Type), "Seq_Equal"),
                                    new RtlExp[] { G(binary.E0), G(binary.E1) }));

            case BinaryExpr.ResolvedOpcode.SeqNeq:
                return(new RtlLiteral("(!" +
                                      new RtlApply(dafnySpec.GetSeqOperationName(AppType(binary.E0.Type), "Seq_Equal"),
                                                   new RtlExp[] { G(binary.E0), G(binary.E1) }) + ")"));

            case BinaryExpr.ResolvedOpcode.Concat:
                return(new RtlApply(dafnySpec.GetSeqOperationName(AppType(binary.Type), "Seq_Append"),
                                    new RtlExp[] { G(binary.E0), G(binary.E1) }));
            }
            if (binary.Op == BinaryExpr.Opcode.Exp)
            {
                binary = new BinaryExpr(binary.tok, BinaryExpr.Opcode.Imp, binary.E0, binary.E1);
            }
            switch (binary.Op)
            {
            case BinaryExpr.Opcode.Disjoint:
            case BinaryExpr.Opcode.In:
            case BinaryExpr.Opcode.NotIn:
                throw new Exception("not implemented: binary operator '" + BinaryExpr.OpcodeString(binary.Op) + "'");
            }
            if (AppType(binary.E0.Type) is IntType && AppType(binary.E1.Type) is IntType)
            {
                switch (binary.Op)
                {
                case BinaryExpr.Opcode.Le: internalOp = "INTERNAL_le_boogie"; break;

                case BinaryExpr.Opcode.Lt: internalOp = "INTERNAL_lt_boogie"; break;

                case BinaryExpr.Opcode.Ge: internalOp = "INTERNAL_ge_boogie"; break;

                case BinaryExpr.Opcode.Gt: internalOp = "INTERNAL_gt_boogie"; break;

                case BinaryExpr.Opcode.Add: internalOp = "INTERNAL_add_boogie"; break;

                case BinaryExpr.Opcode.Sub: internalOp = "INTERNAL_sub_boogie"; break;

                case BinaryExpr.Opcode.Mul:
                    op = "*";
                    if (thisFuncName != "INTERNAL_mul")
                    {
                        internalOp = FunName("INTERNAL__mul");
                    }
                    break;

                case BinaryExpr.Opcode.Div:
                    op = "div";
                    if (thisFuncName != "INTERNAL_div")
                    {
                        internalOp = FunName("INTERNAL__div");
                    }
                    break;

                case BinaryExpr.Opcode.Mod:
                    op = "mod";
                    if (thisFuncName != "INTERNAL_mod")
                    {
                        internalOp = FunName("INTERNAL__mod");
                    }
                    break;

                default:
                    op = BinaryExpr.OpcodeString(binary.Op);
                    break;
                }
            }
            else
            {
                op = BinaryExpr.OpcodeString(binary.Op);
            }
            if (internalOp == null)
            {
                return(new RtlBinary(op, G(binary.E0), G(binary.E1)));
            }
            else
            {
                return(new RtlApply(internalOp, new RtlExp[]
                                    { G(binary.E0), G(binary.E1) }));
            }
        }
        else if (unary != null && unary.Op == UnaryExpr.Opcode.Not)
        {
            return(new RtlLiteral("(!(" + G(unary.E) + "))"));
        }
        else if (unary != null && unary.Op == UnaryExpr.Opcode.SeqLength)
        {
            return(new RtlApply(dafnySpec.GetSeqOperationName(AppType(unary.E.Type), "Seq_Length"),
                                new RtlExp[] { G(unary.E) }));
        }
        else if (ite != null)
        {
            return(GhostIfThenElse(G(ite.Test), () => G(ite.Thn), () => G(ite.Els)));
        }
        else if (funCall != null)
        {
            switch (funCall.Function.Name)
            {
            case "left":
            case "right":
            case "relation":
            case "public":
                Util.Assert(funCall.Args.Count == 1);
                return(new RtlApply(funCall.Function.Name, new RtlExp[] { G(funCall.Args[0]) }));

            case "sizeof":
                Util.Assert(funCall.Args.Count == 1);
                return(new RtlApply(funCall.Function.Name + "##" + TypeString(AppType(funCall.Args[0].Type)),
                                    new RtlExp[] { G(funCall.Args[0]) }));

            case "INTERNAL_add_raw":
                Util.Assert(funCall.Args.Count == 2);
                return(new RtlBinary("+", G(funCall.Args[0]), G(funCall.Args[1])));

            case "INTERNAL_sub_raw":
                Util.Assert(funCall.Args.Count == 2);
                return(new RtlBinary("-", G(funCall.Args[0]), G(funCall.Args[1])));

            case "IntToReal":
                Util.Assert(funCall.Args.Count == 1);
                return(new RtlApply("real", new RtlExp[] { G(funCall.Args[0]) }));

            case "RealToInt":
                Util.Assert(funCall.Args.Count == 1);
                return(new RtlApply("int", new RtlExp[] { G(funCall.Args[0]) }));
            }
            TypeApply app = dafnySpec.Compile_Function(funCall.Function,
                                                       funCall.TypeArgumentSubstitutions.ToDictionary(p => p.Key, p => AppType(p.Value)));
            string        name     = FunName(SimpleName(app.AppName()));
            string        fullName = FunName(SimpleName(app.AppFullName()));
            List <RtlExp> rtlArgs  = funCall.Args.Select(G).ToList();
            List <RtlExp> rtlReads = funCall.Function.Reads.Where(e => e.Field != null).ToList()
                                     .ConvertAll(e => (RtlExp) new RtlVar(
                                                     GhostVar(e.FieldName), e.Field.IsGhost, AppType(e.Field.Type)));
            rtlArgs = rtlReads.Concat(rtlArgs).ToList();
            if (name.EndsWith("__INTERNAL__HEAP"))
            {
                name = name.Substring(0, name.Length - "__INTERNAL__HEAP".Length);
            }
            else if (DafnySpec.IsHeapFunction(funCall.Function))
            {
                rtlArgs.Insert(0, new RtlLiteral(inRequiresOrOld ? "$absMem_old" : "$absMem"));
            }
            if (Attributes.Contains(funCall.Function.Attributes, "opaque") &&
                funCall.Function.Formals.Count + rtlReads.Count == 0)
            {
                rtlArgs.Insert(0, new RtlLiteral("true"));
            }
            if (fullName == recFunName)
            {
                name = fullName;
            }
            if (name == recFunName)
            {
                recCalls.Add(new List <RtlExp>(rtlArgs));
                rtlArgs.Insert(0, new RtlApply("decreases_" + name, new List <RtlExp>(rtlArgs)));
                rtlArgs.Insert(1, new RtlLiteral(inRecSpec ? "__unroll" : "__unroll + 1"));
                name = "rec_" + name;
            }
            return(new RtlApply(name, rtlArgs));
        }
        else if (dataVal != null)
        {
            bool isSeq = dataVal.Type.TypeName(null).StartsWith("Seq<");
            return(new RtlApply((isSeq ? "_" : "") + dafnySpec.Compile_Constructor(
                                    dataVal.Type, dataVal.Ctor.Name, dataVal.InferredTypeArgs, typeApply.typeArgs).AppName(),
                                dataVal.Arguments.Select(G)));
        }
        else if (existsExp != null || forallExp != null)
        {
            QuantifierExpr qExp               = (QuantifierExpr)exp;
            bool           isForall           = forallExp != null;
            var            varTuples          = qExp.BoundVars.Select(v => Tuple.Create(GhostVar(v.Name), v.IsGhost, v.Type));
            var            oldRenamer         = PushRename(qExp.BoundVars.Select(v => v.Name));
            var            oldStmtExprEnabled = stmtExprEnabled;
            stmtExprEnabled = false;
            RtlExp rExp = new RtlLiteral((isForall ? "(forall " : "(exists ")
                                         + string.Join(", ", qExp.BoundVars.Select(v => GhostVar(v.Name) + ":" + TypeString(AppType(v.Type))))
                                         + " :: " + Triggers(qExp.Attributes, G) + " "
                                         + GetTypeWellFormedExp(varTuples.ToList(), isForall ? "==>" : "&&", G(qExp.Term)) + ")");
            stmtExprEnabled = oldStmtExprEnabled;
            PopRename(oldRenamer);
            return(rExp);
        }
        else if (letExp != null)
        {
            List <RtlExp> rhss;
            if (letExp.Exact)
            {
                rhss = letExp.RHSs.ConvertAll(e => G(e));
            }
            else if (letExp.LHSs.Count == 1 && LiteralExpr.IsTrue(letExp.RHSs[0]) && AppType(letExp.LHSs[0].Var.Type) is IntType)
            {
                rhss = new List <RtlExp> {
                    new RtlLiteral("0")
                };
            }
            else
            {
                throw new Exception("not implemented: LetExpr: " + letExp);
            }
            return(GhostLet(exp.tok, letExp.LHSs.ConvertAll(lhs => lhs.Var), rhss, () => G(letExp.Body)));
        }
        else if (matchExp != null)
        {
            if (matchExp.MissingCases.Count != 0)
            {
                throw new Exception("not implemented: MatchExpr with missing cases: " + matchExp);
            }
            //- match src case c1(ps1) => e1 ... cn(psn) => en
            //-   -->
            //- let x := src in
            //-   if x is c1 then let ps1 := ...x.f1... in e1 else
            //-   if x is c2 then let ps2 := ...x.f2... in e2 else
            //-                   let ps3 := ...x.f3... in e3
            var           src   = G(matchExp.Source);
            var           cases = matchExp.Cases;
            string        x     = TempName();
            Func <RtlExp> body  = null;
            for (int i = cases.Count; i > 0;)
            {
                i--;
                MatchCaseExpr         c     = cases[i];
                Func <List <RtlExp> > cRhss = () => c.Ctor.Formals.ConvertAll(f => (RtlExp) new RtlLiteral("("
                                                                                                           + f.Name + "#" + c.Ctor.Name + "(" + GhostVar(x) + "))"));
                Func <RtlExp> ec = () => GhostLet(exp.tok, c.Arguments, cRhss(), () => G(c.Body));
                if (body == null)
                {
                    body = ec;
                }
                else
                {
                    var prevBody = body;
                    body = () => GhostIfThenElse(new RtlLiteral("(" + GhostVar(x) + " is " + c.Ctor.Name + ")"),
                                                 ec, prevBody);
                }
            }
            return(GhostLet(exp.tok, new List <BoundVar> {
                new BoundVar(exp.tok, x, matchExp.Source.Type)
            },
                            new List <RtlExp> {
                src
            }, body));
        }
        else if (oldExp != null)
        {
            return(new RtlLiteral("old(" + GhostExpression(oldExp.E, inRecSpec, true) + ")"));
        }
        else if (freshExp != null)
        {
            Util.Assert(DafnySpec.IsArrayType(freshExp.E.Type));
            string abs = G(freshExp.E) + ".arrAbs";
            return(new RtlLiteral("(heap_old.absData[" + abs + "] is AbsNone)"));
        }
        else if (fieldSelect != null && fieldSelect.FieldName.EndsWith("?"))
        {
            string constructor = fieldSelect.FieldName.Substring(0, fieldSelect.FieldName.Length - 1);
            constructor = dafnySpec.Compile_Constructor(fieldSelect.Obj.Type, constructor, null, typeApply.typeArgs).AppName();
            bool isSeq = fieldSelect.Obj.Type.TypeName(null).StartsWith("Seq<");
            return(isSeq
                ? new RtlLiteral("is_" + constructor + "(" + G(fieldSelect.Obj) + ")")
                : new RtlLiteral("((" + G(fieldSelect.Obj) + ") is " + constructor + ")"));
        }
        else if (fieldSelect != null && !fieldSelect.Field.IsStatic && AppType(fieldSelect.Obj.Type) is UserDefinedType &&
                 fieldSelect.Field is DatatypeDestructor)
        {
            DatatypeDestructor field       = (DatatypeDestructor)fieldSelect.Field;
            string             constructor = dafnySpec.Compile_Constructor(fieldSelect.Obj.Type,
                                                                           field.EnclosingCtor.Name, null, typeApply.typeArgs).AppName();
            bool isSeq = fieldSelect.Obj.Type.TypeName(null).StartsWith("Seq<");
            return(new RtlLiteral("(" + fieldSelect.FieldName + (isSeq ? "_" : "#") + constructor
                                  + "(" + G(fieldSelect.Obj) + "))"));
        }
        else if (fieldSelect != null && DafnySpec.IsArrayType(AppType(fieldSelect.Obj.Type)) &&
                 fieldSelect.FieldName == "Length")
        {
            return(new RtlLiteral("(Arr_Length(" + G(fieldSelect.Obj) + "))"));
        }
        else if (fieldSelect != null && fieldSelect.Obj is ImplicitThisExpr)
        {
            //- we don't support objects yet, so interpret this as a global variable
            return(new RtlVar(GhostVar(fieldSelect.FieldName), true, fieldSelect.Type));
        }
        else if (seqSelect != null)
        {
            if (seqSelect.SelectOne && DafnySpec.IsArrayType(AppType(seqSelect.Seq.Type)))
            {
                return(new RtlExpComputed(e => "fun_INTERNAL__array__elems__index("
                                          + (inRequiresOrOld ? "$absMem_old" : "$absMem") + "[" + e.args[0] + ".arrAbs], ("
                                          + e.args[1] + "))", new RtlExp[] { G(seqSelect.Seq), G(seqSelect.E0) }));
            }
            else if (seqSelect.SelectOne)
            {
                return(new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqSelect.Seq.Type), "Seq_Index"),
                                    new RtlExp[] { G(seqSelect.Seq), G(seqSelect.E0) }));
            }
            else
            {
                RtlExp seq = G(seqSelect.Seq);
                if (DafnySpec.IsArrayType(AppType(seqSelect.Seq.Type)))
                {
                    seq = new RtlApply(FunName("Seq__FromArray"), new RtlExp[] {
                        new RtlLiteral(inRequiresOrOld ? "$absMem_old" : "$absMem"), seq
                    });
                }
                if (seqSelect.E1 != null)
                {
                    seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqSelect.Type), "Seq_Take"),
                                       new RtlExp[] { seq, G(seqSelect.E1) });
                }
                if (seqSelect.E0 != null)
                {
                    seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqSelect.Type), "Seq_Drop"),
                                       new RtlExp[] { seq, G(seqSelect.E0) });
                }
                return(seq);
            }
        }
        else if (seqUpdate != null)
        {
            if (seqUpdate.ResolvedUpdateExpr != null)
            {
                return(GhostExpressionRec(seqUpdate.ResolvedUpdateExpr, inRecSpec, inRequiresOrOld));
            }
            return(new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqUpdate.Seq.Type), "Seq_Update"),
                                new RtlExp[] { G(seqUpdate.Seq), G(seqUpdate.Index), G(seqUpdate.Value) }));
        }
        else if (seqDisplay != null)
        {
            RtlExp seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqDisplay.Type), "Seq_Empty"), new RtlExp[0]);
            foreach (Expression ei in seqDisplay.Elements)
            {
                seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqDisplay.Type), "Seq_Build"),
                                   new RtlExp[] { seq, G(ei) });
            }
            return(seq);
        }
        else
        {
            throw new Exception("not implemented: " + exp);
        }
    }
Example #28
0
 internal static bool NeedsAutoTriggers(QuantifierExpr quantifier)
 {
     Contract.Requires(quantifier.SplitQuantifier == null); // Don't call this on a quantifier with a Split clause: it's not a real quantifier
     return(!Attributes.Contains(quantifier.Attributes, "trigger") && WantsAutoTriggers(quantifier));
 }
Example #29
0
        public Expression TreeToExpression()
        {
            Contract.Ensures(Contract.Result <Expression>() != null);
            if (IsLeaf())
            {
                return(Data);
            }
            if (Data is TacnyBinaryExpr)
            {
                TacnyBinaryExpr bexp = (TacnyBinaryExpr)Data;
                Expression      E0   = LChild.TreeToExpression();
                Expression      E1   = RChild?.TreeToExpression();
                return(new TacnyBinaryExpr(bexp.tok, bexp.Op, E0, E1));
            }
            if (Data is BinaryExpr)
            {
                BinaryExpr bexp = (BinaryExpr)Data;
                Expression E0   = LChild.TreeToExpression();
                Expression E1   = RChild?.TreeToExpression();

                return(new BinaryExpr(bexp.tok, bexp.Op, E0, E1));
            }
            if (Data is ChainingExpression)
            {
                List <Expression>  operands = null;
                ChainingExpression ce       = (ChainingExpression)Data;
                operands = GetLeafData();
                operands.RemoveAt(1); // hack to remove the duplicate name statement
                List <BinaryExpr.Opcode> operators = new List <BinaryExpr.Opcode>();
                BinaryExpr expr = (BinaryExpr)LChild.TreeToExpression();
                operators.Add(((BinaryExpr)expr.E0).Op);
                operators.Add(((BinaryExpr)expr.E1).Op);
                return(new ChainingExpression(ce.tok, operands, operators, ce.PrefixLimits, expr));
            }
            if (Data is ParensExpression)
            {
                return(new ParensExpression(Data.tok, LChild.TreeToExpression()));
            }
            if (Data is QuantifierExpr)
            {
                QuantifierExpr qexp = (QuantifierExpr)Data;

                if (Data is ForallExpr)
                {
                    return(new ForallExpr(qexp.tok, qexp.BoundVars, qexp.Range, LChild.TreeToExpression(), qexp.Attributes));
                }
                if (Data is ExistsExpr)
                {
                    return(new ExistsExpr(qexp.tok, qexp.BoundVars, qexp.Range, LChild.TreeToExpression(), qexp.Attributes));
                }
            }
            else if (Data is NegationExpression)
            {
                return(new NegationExpression(Data.tok, LChild.TreeToExpression()));
            }
            else if (Data is SeqSelectExpr)
            {
                var e = (SeqSelectExpr)Data;
                return(new SeqSelectExpr(e.tok, e.SelectOne, e.Seq, LChild.TreeToExpression(), RChild?.TreeToExpression()));
            }

            return(Data);
        }
Example #30
0
 internal static bool AllowsMatchingLoops(QuantifierExpr quantifier)
 {
     Contract.Requires(quantifier.SplitQuantifier == null); // Don't call this on a quantifier with a Split clause: it's not a real quantifier
     // This is different from nowarn: it won't remove loops at all, even if another trigger is available.
     return(Attributes.Contains(quantifier.Attributes, "matchingloop"));
 }