コード例 #1
0
    public TypeApply Compile_Method(Method method, Dictionary <TypeParameter, Type> typeArgs, List <TypeParameter> extraTypeParams = null)
    {
        Dictionary <string, TypeParameter> substArgs = new Dictionary <string, TypeParameter>();
        var fullTypeArgs = method.TypeArgs.Concat(extraTypeParams ?? new List <TypeParameter>()).ToList();

        fullTypeArgs.ForEach(t => substArgs.Add(t.Name, t));
        typeArgs = typeArgs.ToDictionary(p => substArgs[p.Key.Name], p => p.Value);
        TypeApply apply = new TypeApply(this, DafnySpec.SanitizedName(method), fullTypeArgs, typeArgs);

        //Console.Error.WriteLine("Compile_Method: " + method + " :: " + method.GetType() + " " + String.Join(",", typeArgs));
        if (!compileMethods.ContainsKey(apply))
        {
            //Console.Error.WriteLine("Compile_Method# " + method + " :: " + method.GetType() + " " + String.Join(",", typeArgs));
            compileMethods.Add(apply, apply);
            var tok     = method.tok;
            var writers = ChooseWriter(tok, method.Name, apply);
            CompileMethodGhost compile = NewCompileMethod(this, method, apply,
                                                          writers.Item1, writers.Item2, writers.Item3, writers.Item4);
            if (writers.Item3 == "Seq" && typeArgs.Count == 1)
            {
                compile.visibleElementType = new List <Type>(apply.typeArgs.Values)[0];
            }
            compile.minVerify = minVerify;
            try
            {
                compile.Compile();
            }
            catch (Exception e)
            {
                throw new Exception("while compiling method " + method.Name, e);
            }
        }
        return(apply);
    }
コード例 #2
0
    public TypeApply Compile_Function(Function function, Dictionary <TypeParameter, Type> typeArgs)
    {
        Dictionary <string, TypeParameter> substArgs = new Dictionary <string, TypeParameter>();

        function.TypeArgs.ForEach(t => substArgs.Add(t.Name, t));
        typeArgs = typeArgs.ToDictionary(p => substArgs[p.Key.Name], p => p.Value);
        TypeApply apply = new TypeApply(this, DafnySpec.SanitizedName(function), function.TypeArgs, typeArgs);

        if (!compileFunctions.ContainsKey(apply))
        {
            compileFunctions.Add(apply, apply);
            var tok = function.tok;
            //Console.Error.WriteLine("function: " + function + " :: " + function.GetType());
            //Console.Error.WriteLine("    " + function.Body);
            //Console.Error.WriteLine("    " + function.IsRecursive + " " + function.IsGhost);
            var writers = ChooseWriter(tok, function.Name, apply);
            if (!Attributes.Contains(function.Attributes, "imported"))
            {
                try
                {
                    var compile = new CompileFunction(this, function, apply, writers.Item1, writers.Item2,
                                                      writers.Item3, writers.Item4);
                    if (writers.Item3 == "Seq" && typeArgs.Count == 1)
                    {
                        compile.visibleElementType = new List <Type>(apply.typeArgs.Values)[0];
                    }
                    compile.minVerify = minVerify;
                    compile.Compile();
                }
                catch (Exception e)
                {
                    throw new Exception("while compiling function " + function.Name, e);
                }
            }
            else
            {
                // imported
                if (function.Ens.Count > 0)
                {
                    string name = FunName(SimpleName(apply.AppName()));
                    AddLemma(new LemmaCall(writers.Item3, (Type)null,
                                           "call lemma_fun_ensures_" + name + "();", false));
                }
            }
            bool hidden = Attributes.Contains(function.Attributes, "opaque");
            bool isFull = function.Name.Contains("#") && function.Name.EndsWith("_FULL");
            if (!function.IsGhost && !isFull && !IsSpecFile(function.tok.filename))
            {
                Compile_FunctionAsMethod(function, typeArgs, substArgs);
            }
        }
        return(apply);
    }
コード例 #3
0
 public CompileBase(DafnySpec dafnySpec, TypeApply typeApply,
                    TextWriter writer, TextWriter iwriter, string moduleName, List <string> imports)
 {
     this.dafnySpec      = dafnySpec;
     this.typeApply      = typeApply;
     this.writer         = writer;
     this.iwriter        = iwriter;
     this.moduleName     = moduleName;
     this.imports        = imports;
     this.visibleModules = imports.Concat(new List <string> {
         moduleName, "private##" + moduleName
     }).ToList();
 }
コード例 #4
0
 public void Compile()
 {
     if (Attributes.Contains(field.Attributes, "imported"))
     {
         //- do nothing
     }
     else if (field.IsGhost)
     {
         string rw = Attributes.Contains(field.Attributes, "readonly") ? "readonly " : "";
         iwriter.WriteLine(rw + "var " + "$ghost_" + DafnySpec.CleanName(field.Name) + ":"
                           + dafnySpec.TypeString(field.Type) + ";");
     }
     else
     {
         throw new Exception("not implemented: non-ghost global variables");
     }
 }
コード例 #5
0
    public TypeApply(DafnySpec dafnySpec, string name, List <TypeParameter> typeParams, Dictionary <TypeParameter, Type> typeArgs)
    {
        this.dafnySpec  = dafnySpec;
        this.name       = name;
        this.typeParams = typeParams;
        this.typeArgs   = new Dictionary <TypeParameter, Type>();
        typeArgs.ToList().ForEach(a => this.typeArgs.Add(a.Key, ToType(a.Value)));
        this.typeSubsts = new Dictionary <string, Type>();
        typeArgs.ToList().ForEach(a => this.typeSubsts.Add(a.Key.Name, ToType(a.Value)));

        string suffix = String.Concat(typeParams.Select(p => "___" + dafnySpec.TypeString(typeArgs[p])));

        appName     = name + suffix;
        appFullName = name + "__FULL" + suffix;
        int i = appFullName.Contains('.') ? appFullName.LastIndexOf('.') + 1 : 0;

        appFullName = appFullName.Insert(i, DafnySpec.CleanName("#"));
    }
コード例 #6
0
ファイル: Compile.cs プロジェクト: jango2015/Ironclad
 public TypeApply(DafnySpec dafnySpec, string name, List<TypeParameter> typeParams, Dictionary<TypeParameter,Type> typeArgs)
 {
     
     
     this.dafnySpec = dafnySpec;
     this.name = name;
     this.typeParams = typeParams;
     this.typeArgs = new Dictionary<TypeParameter,Type>();
     typeArgs.ToList().ForEach(a => this.typeArgs.Add(a.Key, ToType(a.Value)));
     this.typeSubsts = new Dictionary<string,Type>();
     typeArgs.ToList().ForEach(a => this.typeSubsts.Add(a.Key.Name, ToType(a.Value)));
     
     string suffix = String.Concat(typeParams.Select(p => "___" + dafnySpec.TypeString(typeArgs[p])));
     appName = name + suffix;
     appFullName = name + "__FULL" + suffix;
     int i = appFullName.Contains('.') ? appFullName.LastIndexOf('.') + 1 : 0;
     appFullName = appFullName.Insert(i, DafnySpec.CleanName("#"));
 }
コード例 #7
0
    public string DecreasesExp(ICallable target)
    {
        Util.Assert(!isPrinting);
        Expression decrease;

        if (target.Decreases.Expressions.Count == 0 && target.Ins.Count > 0)
        {
            decrease = DafnySpec.MakeIdentifierExpr(target.Ins[0].Name, target.Ins[0].Type,
                                                    target.Ins[0].IsGhost);
        }
        else if (target.Decreases.Expressions.Count == 1)
        {
            decrease = target.Decreases.Expressions[0];
        }
        else if (target.Decreases.Expressions.Count > 1)
        {
            decrease = target.Decreases.Expressions[0];
        }
        else
        {
            throw new Exception("recursive methods must have at least one parameter or supply a decreases clause");
        }
        Type decreaseType = AppType(decrease.Type);

        if (decreaseType.AsDatatype != null)
        {
            return("sizeof##" + TypeString(decreaseType) + "(" + GhostExpression(decrease) + ")");
        }
        else if (decreaseType is SeqType)
        {
            return(new RtlApply(dafnySpec.GetSeqOperationName(decreaseType, "Seq_Length"),
                                new RtlExp[] { GhostExpression(decrease) }).ToString());
        }
        else if (decreaseType.Equals(Type.Int))
        {
            return(GhostExpression(decrease).ToString());
        }
        else
        {
            throw new Exception("decreases clauses must be an integer or datatype");
        }
    }
コード例 #8
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);
        }
    }
コード例 #9
0
 public string GhostVar(string x, bool allowRename = true)
 {
     return((x == "INTERNAL_absMem") ? "$absMem"
         : "$ghost_" + (allowRename && renamer.ContainsKey(x) ? renamer[x] : "") + DafnySpec.CleanName(x));
 }
コード例 #10
0
ファイル: DafnyCC.cs プロジェクト: jango2015/Ironclad
 public override CompileMethodGhost NewCompileMethod(DafnySpec dafnySpec, Method method,
     TypeApply typeApply, TextWriter writer, TextWriter iwriter, string moduleName, List<string> imports)
 {
     return new CompileMethod(dafnySpec, method, typeApply, writer, iwriter, moduleName, imports);
 }
コード例 #11
0
    public void Compile()
    {
        Util.Assert(!isPrinting);
        string        name       = FunName(DafnySpec.SimpleName(typeApply.AppName()));
        string        fullName   = FunName(DafnySpec.SimpleName(typeApply.AppFullName()));
        bool          isAxiom    = Attributes.Contains(function.Attributes, "axiom");
        bool          isPrivate  = Attributes.Contains(function.Attributes, "private");
        bool          hidden     = Attributes.Contains(function.Attributes, "opaque");
        bool          isHeap     = DafnySpec.IsHeapFunction(function);
        List <string> heapParams = isHeap ? new List <string> {
            "$absMem:[int][int]int"
        } : new List <string>();
        List <string> heapArgs = isHeap ? new List <string> {
            "$absMem"
        } : new List <string>();
        var formals = function.Formals;
        var reads   = function.Reads.Where(e => e.Field != null).ToList().ConvertAll(e =>
                                                                                     new Formal(e.tok, e.FieldName, e.Field.Type, true, e.Field.IsGhost));

        formals = reads.Concat(formals).ToList();
        if (hidden && formals.Count == 0)
        {
            formals = new List <Formal> {
                new Formal(function.tok, "___dummy", Type.Bool, true, true)
            };
        }
        if (hidden && !function.Name.EndsWith("_FULL"))
        {
            ClassDecl cls  = (ClassDecl)function.EnclosingClass;
            Function  full = (Function)cls.Members.Find(m => m.Name == "#" + function.Name + "_FULL");
            dafnySpec.Compile_Function(full, typeApply.typeArgs);
        }
        bool   isFull     = hidden && function.Name.EndsWith("_FULL");
        string unfullName = isFull ? name.Substring(0, name.Length - "__FULL".Length)
                            .Replace("#", "").Replace("____HASH", "") : null;

        string        argsNoRec = String.Join(", ", heapArgs.Concat(formals.Select(f => GhostVar(f.Name))));
        List <RtlExp> reqsNoRec = minVerify ? new List <RtlExp>() : function.Req.ConvertAll(e => GhostExpression(e, true));
        List <RtlExp> enssNoRec = minVerify ? new List <RtlExp>() : function.Ens.ConvertAll(e => GhostExpression(e, true));

        AddTypeWellFormed(reqsNoRec, formals);
        AddTypeWellFormed(enssNoRec, name + "(" + argsNoRec + ")", function.IsGhost, function.ResultType);
        if (function.Body != null && !minVerify)
        {
            recFunName      = name;
            stmtExprEnabled = true;
            GhostExpression(function.Body);
            function.IsRecursive = recCalls.Count != 0;
            stmtExprEnabled      = false;
            stmts      = new List <RtlStmt>();
            recCalls   = new List <List <RtlExp> >();
            recFunName = null;
        }
        if (function.IsRecursive)
        {
            recFunName = name;
        }
        stmts           = new List <RtlStmt>();
        stmtExprEnabled = true;
        var            bodyDecls = PushForall();
        RtlExp         body      = (function.Body == null || minVerify) ? null : GhostExpression(function.Body);
        List <RtlStmt> bodyStmts = stmts;

        PopForall();
        stmtExprEnabled = false;
        stmts           = new List <RtlStmt>();
        string parms = String.Join(", ", heapParams.Concat(
                                       formals.Select(f => GhostVar(f.Name) + ":" + TypeString(AppType(f.Type)))));
        string args = String.Join(", ", heapArgs.Concat(
                                      formals.Select(f => GhostVar(f.Name))));
        string        sep       = (heapArgs.Count + formals.Count != 0) ? ", " : "";
        string        ret       = TypeString(AppType(function.ResultType));
        string        recName   = "rec_" + name;
        string        decreases = null;
        List <RtlExp> reqs      = minVerify ? new List <RtlExp>() : function.Req.ConvertAll(e => GhostExpression(e, true));
        List <RtlExp> enss      = minVerify ? new List <RtlExp>() : function.Ens.ConvertAll(e => GhostExpression(e, true));

        AddTypeWellFormed(reqs, formals);
        AddTypeWellFormed(enss, name + "(" + args + ")", function.IsGhost, function.ResultType);
        string reqConjunct = "(true" + String.Concat(reqs.Select(e => " && (" + e + ")")) + ")";
        string ensConjunct = "(true" + String.Concat(enss.Select(e => " && (" + e + ")")) + ")";

        Util.Assert(!isPrinting);
        if (function.IsRecursive && function.Body != null && !minVerify)
        {
            decreases = DecreasesExp(function);
        }
        List <RtlExp> enssRec = null;

        if (function.IsRecursive && (!hidden || isFull) && body != null && !minVerify)
        {
            enssRec = function.Ens.ConvertAll(e => GhostExpression(e, true));
        }
        isPrinting = true;
        var fiWriter = isPrivate ? writer : iwriter;

        if (function.IsRecursive && function.Body != null && !minVerify)
        {
            iwriter.WriteLine("function decreases0_" + name + "(" + parms + "):int { " + decreases + " }");
            iwriter.WriteLine("function decreases_" + name + "(" + parms + "):int { if decreases0_"
                              + name + "(" + args + ") < 0 then 0 else 1 + decreases0_" + name + "(" + args + ") }");
            iwriter.WriteLine("function " + recName + "(__decreases:int, __unroll:int" + sep + parms
                              + "):" + ret + ";");
            fiWriter.WriteLine("function implementation{" + FunName("unroll") + "(__unroll), "
                               + recName + "(__decreases, __unroll" + sep + args + ")} "
                               + recName + "(__decreases:int, __unroll:int" + sep + parms + "):" + ret);
            fiWriter.WriteLine("{");
            fiWriter.WriteLine("    " + body.ToString());
            fiWriter.WriteLine("}");
        }
        iwriter.WriteLine("function " + name + "(" + parms + "):" + ret + ";");
        if (hidden && !isFull && !minVerify)
        {
            iwriter.WriteLine("function unhide_" + name + "(" + parms + "):bool { true }");
            fiWriter.WriteLine("function implementation{unhide_" + name + "(" + args + ")} "
                               + name + "(" + parms + "):" + ret);
            fiWriter.WriteLine("{");
            fiWriter.WriteLine("    " + fullName + "(" + args + ")");
            fiWriter.WriteLine("}");
            iwriter.WriteLine("atomic ghost procedure "
                              + GhostProcName("reveal__" + DafnySpec.SimpleName(typeApply.AppName())) + "();");
            string forall = "forall " + parms + "::" + name + "(" + args + ") == "
                            + fullName + "(" + args + ")";
            iwriter.WriteLine("    ensures (" + forall + ");");
            writer.WriteLine("implementation "
                             + GhostProcName("reveal__" + DafnySpec.SimpleName(typeApply.AppName())) + "()");
            writer.WriteLine("{");
            writer.WriteLine("    " + forall);
            writer.WriteLine("    {");
            writer.WriteLine("        assert unhide_" + name + "(" + args + ");");
            writer.WriteLine("    }");
            writer.WriteLine("}");
        }
        if (body != null && (!hidden || isFull))
        {
            fiWriter.WriteLine("function implementation{" + name + "(" + args + ")" + "} " + name
                               + "(" + parms + "):" + ret);
            fiWriter.WriteLine("{");
            if (function.IsRecursive)
            {
                fiWriter.WriteLine("    " + recName + "(decreases_" + name + "(" + args + "), 0" + sep + args + ")");
            }
            else
            {
                fiWriter.WriteLine("    " + body.ToString());
            }
            fiWriter.WriteLine("}");
        }
        if (function.IsRecursive && (!hidden || isFull) && body != null && !minVerify)
        {
            AddTypeWellFormed(enssRec, recName + "(__decreases, __unroll" + sep + args + ")",
                              function.IsGhost, function.ResultType);
            string ensRecConjunct = "(true" + String.Concat(enssRec.Select(e => " && (" + e + ")")) + ")";
            iwriter.WriteLine("atomic ghost procedure lemma_unroll2_" + recName
                              + "(__decreases:int, __unroll:int, __unroll2:int" + sep + parms + ");");
            iwriter.WriteLine("    requires __decreases == decreases_" + name + "(" + args + ");");
            iwriter.WriteLine("    ensures  " + reqConjunct + " ==> " + ensRecConjunct + " && "
                              + recName + "(__decreases, __unroll" + sep + args + ") == "
                              + recName + "(__decreases, __unroll2" + sep + args + ");");

            writer.WriteLine("implementation lemma_unroll2_" + recName
                             + "(__decreases:int, __unroll:int, __unroll2:int" + sep + parms + ")");
            writer.WriteLine("{");
            writer.WriteLine("    " + bodyDecls);
            writer.WriteLine("    assert fun_unroll(__unroll) && fun_unroll(__unroll2);");
            dafnySpec.WriteLemmas(writer, this, visibleModules, function.Attributes);
            writer.WriteLine("    if (" + reqConjunct + ")");
            writer.WriteLine("    {");
            bodyStmts.ForEach(s => writer.WriteLine("    " + s));
            writer.WriteLine("    }");
            foreach (List <RtlExp> recArgs in recCalls)
            {
                string rec_args     = String.Join(", ", recArgs);
                string rec_decrease = "decreases_" + name + "(" + rec_args + ")";
                writer.WriteLine("    if (0 <= " + rec_decrease + " && " + rec_decrease + " < __decreases)");
                writer.WriteLine("    {");
                writer.WriteLine("        call lemma_unroll2_" + recName + "(" + rec_decrease
                                 + ", __unroll + 1, __unroll2 + 1" + sep + rec_args + ");");
                writer.WriteLine("    }");
            }
            writer.WriteLine("}");
            string unroll_args  = "decreases_" + name + "(" + args + "), __unroll";
            string unroll_args0 = "decreases_" + name + "(" + args + "), 0";
            string unroll       = recName + "(" + unroll_args + sep + args + ")";
            string unroll0      = recName + "(" + unroll_args0 + sep + args + ")";


            var    lwriter   = isPrivate ? writer : iwriter;
            string recForall = "forall __unroll:int" + sep + parms + "::"
                               + "{fun_unroll(__unroll), " + unroll + "} "
                               + reqConjunct + " ==> fun_unroll(__unroll) ==> " + unroll + " == " + body;
            lwriter.WriteLine("atomic ghost procedure lemma_unroll_" + recName + "();");
            lwriter.WriteLine("    ensures  (" + recForall + ");");
            writer.WriteLine("implementation lemma_unroll_" + recName + "()");
            writer.WriteLine("{");
            dafnySpec.WriteLemmas(writer, this, visibleModules, function.Attributes);
            writer.WriteLine("    " + recForall);
            writer.WriteLine("    {");
            writer.WriteLine("    " + bodyDecls);
            writer.WriteLine("    if (" + reqConjunct + ")");
            writer.WriteLine("    {");
            bodyStmts.ForEach(s => writer.WriteLine("    " + s));
            writer.WriteLine("    }");
            writer.WriteLine("    }");
            writer.WriteLine("}");
            dafnySpec.AddLemma(new LemmaCall((isPrivate ? "private##" : "") + moduleName,
                                             visibleElementType,
                                             "call lemma_unroll_" + recName + "();",
                                             false));

            Func <string, string> forall = s => "forall __unroll:int" + sep + parms + "::"
                                           + "{" + s + unroll + "} "
                                           + "{fun_unroll__all(__unroll), " + unroll + "} "
                                           + reqConjunct + " ==> " + unroll + " == " + name + "(" + args + ") && " + ensConjunct;
            iwriter.WriteLine("atomic ghost procedure lemma_unroll_" + name + "();");
            iwriter.WriteLine("    ensures  (" + forall(unroll0 + ", ") + ");");
            writer.WriteLine("implementation lemma_unroll_" + name + "()");
            writer.WriteLine("{");
            dafnySpec.WriteLemmas(writer, this, visibleModules, function.Attributes);
            writer.WriteLine("    " + forall(""));
            writer.WriteLine("    {");
            writer.WriteLine("        call lemma_unroll2_" + recName + "("
                             + unroll_args + ", 0" + sep + args + ");");
            writer.WriteLine("        if (" + reqConjunct + ")");
            writer.WriteLine("        {");
            enss.ForEach(e => writer.WriteLine("            assert " + e + ";"));
            writer.WriteLine("        }");
            writer.WriteLine("    }");
            writer.WriteLine("}");
            dafnySpec.AddLemma(new LemmaCall(moduleName, visibleElementType,
                                             "call lemma_unroll_" + name + "();", false));
        }
        else if (enssNoRec.Count > 0 && !minVerify)
        {
            string reqConjunctNoRec = "(true" + String.Concat(reqsNoRec.Select(e => " && (" + e + ")")) + ")";
            string ensConjunctNoRec = "(true" + String.Concat(enssNoRec.Select(e => " && (" + e + ")")) + ")";
            iwriter.WriteLine("function trigger_" + name + "(" + parms + "):bool { true }");
            iwriter.WriteLine("atomic ghost procedure lemma_fun_ensures_" + name + "();");
            string forallNoRec = "forall " + parms
                                 + "::{" + name + "(" + argsNoRec + ")}"
                                 + (isFull ? ("{" + unfullName + "(" + argsNoRec + ")}") : "")
                                 + "{trigger_" + name + "(" + argsNoRec + ")}"
                                 + "trigger_" + name + "(" + argsNoRec + ") ==> "
                                 + reqConjunctNoRec + " ==> " + ensConjunctNoRec;
            iwriter.WriteLine("    ensures (" + forallNoRec + ");");
            if (body != null || hidden || isAxiom)
            {
                writer.WriteLine("implementation lemma_fun_ensures_" + name + "()");
                writer.WriteLine("{");
                dafnySpec.WriteLemmas(writer, this, visibleModules, function.Attributes);
                writer.WriteLine("    " + forallNoRec);
                writer.WriteLine("    {");
                writer.WriteLine("        " + bodyDecls);
                writer.WriteLine("        if (" + reqConjunct + ")");
                writer.WriteLine("        {");
                if (isAxiom)
                {
                    writer.WriteLine("        // dummy lemma body for axiom");
                }
                else
                {
                    bodyStmts.ForEach(s => writer.WriteLine("            " + s));
                }
                writer.WriteLine("        }");
                if (hidden && !isFull)
                {
                    writer.WriteLine("        assert unhide_" + name + "(" + argsNoRec + ");");
                }
                if (hidden && isFull)
                {
                    writer.WriteLine("        assert unhide_" + unfullName + "(" + argsNoRec + ");");
                }
                writer.WriteLine("        if (" + reqConjunct + ")");
                writer.WriteLine("        {");
                enssNoRec.ForEach(e => writer.WriteLine("            assert " + e + ";"));
                writer.WriteLine("        }");
                writer.WriteLine("    }");
                writer.WriteLine("}");
            }
            dafnySpec.AddLemma(new LemmaCall(moduleName, visibleElementType,
                                             "call lemma_fun_ensures_" + name + "();", false));
        }
        isPrinting = false;
    }
コード例 #12
0
    public virtual void AddResolvedGhostStatement(Statement stmt)
    {
        BlockStmt          block      = stmt as BlockStmt;
        IfStmt             ifStmt     = stmt as IfStmt;
        AssertStmt         assertStmt = stmt as AssertStmt;
        AssignStmt         assignStmt = stmt as AssignStmt;
        CallStmt           callStmt   = stmt as CallStmt;
        VarDecl            varDecl    = stmt as VarDecl;
        CalcStmt           calcStmt   = stmt as CalcStmt;
        ForallStmt         forallStmt = stmt as ForallStmt;
        AssignSuchThatStmt existsStmt = stmt as AssignSuchThatStmt;

        if (block != null)
        {
            var oldRenamer = PushRename();
            block.Body.ForEach(AddGhostStatement);
            PopRename(oldRenamer);
        }
        else if (varDecl != null)
        {
            AddGhostVarDecl(varDecl.Name, varDecl.Type, varDecl.IsGhost);
        }
        else if (minVerify)
        {
            return;
        }
        else if (assignStmt != null)
        {
            ExprRhs expRhs = assignStmt.Rhs as ExprRhs;
            if (expRhs != null)
            {
                FieldSelectExpr fieldSelect = assignStmt.Lhs as FieldSelectExpr;
                RtlVar          destVar;
                if (fieldSelect != null)
                {
                    destVar = new RtlVar(GhostVar(fieldSelect.FieldName), true, fieldSelect.Type);
                }
                else
                {
                    destVar = AsVar(assignStmt.Lhs);
                    Util.Assert(destVar != null);
                }
                stmts.Add(new RtlGhostMove(new RtlVar[] { destVar },
                                           new RtlExp[] { GhostExpression(expRhs.Expr) }));
            }
            else
            {
                throw new Exception("not implemented: " + assignStmt.Rhs);
            }
        }
        else if (callStmt != null)
        {
            AddGhostCall(callStmt.Lhs.ConvertAll(AsVar), callStmt.Args,
                         dafnySpec.Compile_Method(callStmt.Method,
                                                  callStmt.TypeArgumentSubstitutions.ToDictionary(p => p.Key, p => AppType(p.Value))),
                         DafnySpec.IsHeapMethod(callStmt.Method));
            SymdiffLinearityPoint();
        }
        else if (ifStmt != null)
        {
            stmts.Add(new RtlGhostStmtComputed(s => "if (" + s.args[0] + ") {",
                                               new RtlExp[] { GhostExpression(ifStmt.Guard) }));
            Indent();
            AddGhostStatement(ifStmt.Thn);
            Unindent();
            stmts.Add(new RtlGhostStmtComputed(s => "}", new RtlExp[0]));
            if (ifStmt.Els != null)
            {
                stmts.Add(new RtlGhostStmtComputed(s => "if (" + s.args[0] + ") {",
                                                   new RtlExp[] {
                    GhostExpression(new UnaryExpr(Bpl.Token.NoToken, UnaryExpr.Opcode.Not, ifStmt.Guard))
                }));
                Indent();
                AddGhostStatement(ifStmt.Els);
                Unindent();
                stmts.Add(new RtlGhostStmtComputed(s => "}", new RtlExp[0]));
            }
        }
        else if (assertStmt != null)
        {
            stmts.Add(new RtlAssert(GhostExpression(assertStmt.Expr)));
        }
        else if (forallStmt != null)
        {
            var    oldRenamer = PushRename(forallStmt.BoundVars.Select(v => v.Name));
            RtlExp ens        = new RtlLiteral("true");
            foreach (var e in forallStmt.Ens)
            {
                ens = new RtlBinary("&&", ens, GhostExpression(e.E));
            }
            RtlExp range = (forallStmt.Range == null) ? new RtlLiteral("true")
                : GhostExpression(forallStmt.Range);
            List <RtlExp> wellFormed = GetTypeWellFormed(forallStmt.BoundVars.
                                                         Select(x => Tuple.Create(GhostVar(x.Name), x.IsGhost, x.Type)).ToList());
            wellFormed.ForEach(e => range = new RtlBinary("&&", e, range));
            ens = new RtlBinary("==>", range, ens);
            string vars = String.Join(", ", forallStmt.BoundVars.Select(x => GhostVar(x.Name) + ":" +
                                                                        TypeString(AppType(x.Type))));
            stmts.Add(new RtlGhostStmtComputed(s => "forall " + vars + "::(" + s.args[0] + ")",
                                               new List <RtlExp> {
                ens
            }));
            stmts.Add(new RtlGhostStmtComputed(s => "{", new RtlExp[0]));
            Indent();
            stmts.Add(PushForall());
            stmts.Add(new RtlGhostStmtComputed(s => "if (" + s.args[0] + ")",
                                               new List <RtlExp> {
                range
            }));
            stmts.Add(new RtlGhostStmtComputed(s => "{", new RtlExp[0]));
            Indent();
            AddGhostStatement(forallStmt.Body);
            foreach (var e in forallStmt.Ens)
            {
                stmts.Add(new RtlAssert(GhostExpression(e.E)));
            }
            PopForall();
            Unindent();
            stmts.Add(new RtlGhostStmtComputed(s => "}", new RtlExp[0]));
            Unindent();
            stmts.Add(new RtlGhostStmtComputed(s => "}", new RtlExp[0]));
            PopRename(oldRenamer);
        }
        else if (existsStmt != null)
        {
            List <RtlStmt> assigns = new List <RtlStmt>();
            List <RtlVar>  tmps    = new List <RtlVar>();
            List <Tuple <string, bool, Type> > varTuples = new List <Tuple <string, bool, Type> >();
            var oldRenamer = PushRename();
            foreach (var lhs in existsStmt.Lhss)
            {
                IdentifierExpr idExp   = lhs.Resolved as IdentifierExpr;
                RtlVar         origVar = AsVar(lhs);
                AddRename(idExp.Name);
                RtlVar renameVar = AsVar(lhs);
                tmps.Add(renameVar);
                varTuples.Add(Tuple.Create(renameVar.ToString(), true, idExp.Type));
                assigns.Add(new RtlGhostMove(new RtlVar[] { origVar },
                                             new RtlExp[] { renameVar }));
            }
            string vars = String.Join(", ", tmps.Select(x => x.getName() + ":" + TypeString(AppType(x.type))));
            stmts.Add(new RtlGhostStmtComputed(s => "exists " + vars + "::(" + s.args[0] + ");",
                                               new List <RtlExp> {
                GetTypeWellFormedExp(varTuples.ToList(), "&&", GhostExpression(existsStmt.Expr))
            }));
            stmts.AddRange(assigns);
            PopRename(oldRenamer);
        }
        else if (calcStmt != null)
        {
            Util.Assert(calcStmt.Steps.Count == calcStmt.Hints.Count);
            CalcStmt.BinaryCalcOp binOp = calcStmt.Op as CalcStmt.BinaryCalcOp;
            bool isImply = binOp != null && binOp.Op == BinaryExpr.Opcode.Imp && calcStmt.Steps.Count > 0;
            if (isImply)
            {
                stmts.Add(new RtlGhostStmtComputed(s => "if (" + s.args[0] + ")",
                                                   new RtlExp[] { GhostExpression(CalcStmt.Lhs(calcStmt.Steps[0])) }));
                stmts.Add(new RtlGhostStmtComputed(s => "{", new RtlExp[0]));
                Indent();
            }
            var stepCount = calcStmt.Hints.Last().Body.Count == 0 ? calcStmt.Steps.Count - 1 : calcStmt.Steps.Count;
            for (int i = 0; i < stepCount; i++)
            {
                if (calcStmt.Hints[i] == null)
                {
                    stmts.Add(new RtlAssert(GhostExpression(calcStmt.Steps[i])));
                }
                else
                {
                    stmts.Add(new RtlGhostStmtComputed(s => "forall::(" + s.args[0] + ")",
                                                       new List <RtlExp> {
                        GhostExpression(calcStmt.Steps[i])
                    }));
                    stmts.Add(new RtlGhostStmtComputed(s => "{", new RtlExp[0]));
                    Indent();
                    var dict = new Dictionary <string, RtlVar>();
                    stmts.Add(new RtlGhostStmtComputed(s => String.Concat(dict.Values.Select(
                                                                              x => "var " + x.x + ":" + TypeString(x.type) + ";")),
                                                       new RtlExp[0]));
                    forallVars.Add(dict);
                    AddGhostStatement(calcStmt.Hints[i]);
                    forallVars.RemoveAt(forallVars.Count - 1);
                    Unindent();
                    stmts.Add(new RtlGhostStmtComputed(s => "}", new RtlExp[0]));
                }
            }
            if (isImply)
            {
                Unindent();
                stmts.Add(new RtlGhostStmtComputed(s => "}", new RtlExp[0]));
            }
        }
        else
        {
            throw new Exception("not implemented in ghost methods: " + stmt);
        }
    }
コード例 #13
0
 public CompileMethodGhost(DafnySpec dafnySpec, Method method, TypeApply typeApply,
     TextWriter writer, TextWriter iwriter, string moduleName, List<string> imports):
     base(dafnySpec, typeApply, writer, iwriter, moduleName, imports)
 {
     this.method = method;
 }
コード例 #14
0
 public CompileField(DafnySpec dafnySpec, Field field, TextWriter iwriter)
 {
     this.dafnySpec = dafnySpec;
     this.field     = field;
     this.iwriter   = iwriter;
 }
コード例 #15
0
    public RegAlloc(
        DafnySpec dafnySpec,
        CompileMethod compileMethod,
        List <string> inVars,
        List <string> outVars,
        List <Formal> inIntList,
        List <Formal> outIntList,
        List <Formal> inPtrList,
        List <Formal> outPtrList,
        Dictionary <string, RtlVar> allVars,
        List <RtlStmt> stmts) :
        base(inVars, outVars, stmts)
    {
        this.dafnySpec     = dafnySpec;
        this.compileMethod = compileMethod;

        IPSize  = ((DafnyCC)dafnySpec).IPSize;
        IPWords = IPSize / 4;

        if (compileMethod.dafnycc.useFramePointer)
        {
            regs = new List <string>(new string[] { "EAX", "ECX", "EDX", "EBX", "ESI", "EDI" });
        }
        else
        {
            regs = new List <string>(new string[] { "EAX", "ECX", "EDX", "EBX", "ESI", "EDI", "EBP" });
        }
        initAssign = new List <string>(new string[regs.Count]);
        retAssign  = new List <string>(new string[regs.Count]);
        for (int i = 0; i < inIntList.Count; i++)
        {
            inInts.Add(compileMethod.GhostVar(inIntList[i].Name), 4 * i);
        }
        for (int i = 0; i < outIntList.Count; i++)
        {
            outInts.Add(compileMethod.GhostVar(outIntList[i].Name), 4 * i);
        }
        for (int i = 0; i < inPtrList.Count; i++)
        {
            string x = compileMethod.GhostVar(inPtrList[i].Name);
            inPtrs.Add(x, 4 * i);
        }
        for (int i = 0; i < outPtrList.Count; i++)
        {
            string x = compileMethod.GhostVar(outPtrList[i].Name);
            outPtrs.Add(x, 4 * i);
        }
        allVars.ToList().ForEach(p => varTypes.Add(p.Key, p.Value.type));

        /* for now, just use the stack for simplicity
         * if (inVars.Count >= 1)
         * {
         *  initAssign[regs.IndexOf("ECX")] = inVars[0];
         * }
         * if (inVars.Count >= 2)
         * {
         *  initAssign[regs.IndexOf("EDX")] = inVars[1];
         * }
         * if (inVars.Count >= 3)
         * {
         *  initAssign[regs.IndexOf("EBX")] = inVars[2];
         * }
         * if (inVars.Count >= 4)
         * {
         *  throw new Exception("not implemented: more than two arguments");
         * }
         * if (outVars.Count >= 1)
         * {
         *  retAssign[regs.IndexOf("EAX")] = outVars[0];
         * }
         * if (outVars.Count >= 2)
         * {
         *  retAssign[regs.IndexOf("ESI")] = outVars[1];
         * }
         * if (outVars.Count >= 3)
         * {
         *  throw new Exception("not implemented: more than two return values");
         * }
         */
    }
コード例 #16
0
 public bool IsArray(string x)
 {
     return(DafnySpec.IsArrayType(varTypes[x]));
 }
コード例 #17
0
ファイル: CompileFunction.cs プロジェクト: jango2015/Ironclad
 public CompileFunction(DafnySpec dafnySpec, Function function, TypeApply typeApply,
     TextWriter writer, TextWriter iwriter, string moduleName, List<string> imports):
     base(dafnySpec, typeApply, writer, iwriter, moduleName, imports)
 {
     this.function = function;
 }
コード例 #18
0
 static Type ToType(Type t)
 {
     return(DafnySpec.ToType(t));
 }
コード例 #19
0
ファイル: RegAlloc.cs プロジェクト: jango2015/Ironclad
    public RegAlloc(
        DafnySpec dafnySpec,
        CompileMethod compileMethod,
        List<string> inVars,
        List<string> outVars,
        List<Formal> inIntList,
        List<Formal> outIntList,
        List<Formal> inPtrList,
        List<Formal> outPtrList,
        Dictionary<string,RtlVar> allVars,
        List<RtlStmt> stmts):
        base(inVars, outVars, stmts)
    {
        this.dafnySpec = dafnySpec;
        this.compileMethod = compileMethod;
        
        IPSize = ((DafnyCC)dafnySpec).IPSize; 
        IPWords = IPSize/4;

        if (compileMethod.dafnycc.useFramePointer)
        {
            regs = new List<string>(new string[] { "EAX", "ECX", "EDX", "EBX", "ESI", "EDI" });
        }
        else
        {
            regs = new List<string>(new string[] { "EAX", "ECX", "EDX", "EBX", "ESI", "EDI", "EBP" });
        }
        initAssign = new List<string>(new string[regs.Count]);
        retAssign = new List<string>(new string[regs.Count]);
        for (int i = 0; i < inIntList.Count; i++)
        {
            inInts.Add(compileMethod.GhostVar(inIntList[i].Name), 4 * i);
        }
        for (int i = 0; i < outIntList.Count; i++)
        {
            outInts.Add(compileMethod.GhostVar(outIntList[i].Name), 4 * i);
        }
        for (int i = 0; i < inPtrList.Count; i++)
        {
            string x = compileMethod.GhostVar(inPtrList[i].Name);
            inPtrs.Add(x, 4 * i);
        }
        for (int i = 0; i < outPtrList.Count; i++)
        {
            string x = compileMethod.GhostVar(outPtrList[i].Name);
            outPtrs.Add(x, 4 * i);
        }
        allVars.ToList().ForEach(p => varTypes.Add(p.Key, p.Value.type));
        /* for now, just use the stack for simplicity
        if (inVars.Count >= 1)
        {
            initAssign[regs.IndexOf("ECX")] = inVars[0];
        }
        if (inVars.Count >= 2)
        {
            initAssign[regs.IndexOf("EDX")] = inVars[1];
        }
        if (inVars.Count >= 3)
        {
            initAssign[regs.IndexOf("EBX")] = inVars[2];
        }
        if (inVars.Count >= 4)
        {
            throw new Exception("not implemented: more than two arguments");
        }
        if (outVars.Count >= 1)
        {
            retAssign[regs.IndexOf("EAX")] = outVars[0];
        }
        if (outVars.Count >= 2)
        {
            retAssign[regs.IndexOf("ESI")] = outVars[1];
        }
        if (outVars.Count >= 3)
        {
            throw new Exception("not implemented: more than two return values");
        }
        */
        
        
        
        
    }
コード例 #20
0
 public CompileMethodGhost(DafnySpec dafnySpec, Method method, TypeApply typeApply,
                           TextWriter writer, TextWriter iwriter, string moduleName, List <string> imports) :
     base(dafnySpec, typeApply, writer, iwriter, moduleName, imports)
 {
     this.method = method;
 }
コード例 #21
0
 public virtual CompileMethodGhost NewCompileMethod(DafnySpec dafnySpec, Method method,
                                                    TypeApply typeApply, TextWriter writer, TextWriter iwriter, string moduleName, List <string> imports)
 {
     return(new CompileMethodGhost(dafnySpec, method, typeApply, writer, iwriter, moduleName, imports));
 }
コード例 #22
0
 public CompileFunction(DafnySpec dafnySpec, Function function, TypeApply typeApply,
                        TextWriter writer, TextWriter iwriter, string moduleName, List <string> imports) :
     base(dafnySpec, typeApply, writer, iwriter, moduleName, imports)
 {
     this.function = function;
 }
コード例 #23
0
 public static string GhostProcName(string x)
 {
     return(DafnySpec.GhostProcName(x));
 }
コード例 #24
0
 public static string FunName(string x)
 {
     return(DafnySpec.FunName(x));
 }
コード例 #25
0
    public void CompileGhost()
    {
        bool          isAxiom    = Attributes.Contains(method.Attributes, "axiom");
        bool          isHeap     = DafnySpec.IsHeapMethod(method);
        BlockStmt     body       = method.Body;
        List <string> heapParams = isHeap ? new List <string> {
            "$absMem:[int][int]int"
        } : new List <string>();
        List <string> heapArgs = isHeap ? new List <string> {
            "$absMem"
        } : new List <string>();
        string parms = String.Join(", ", heapParams.Concat(
                                       method.Ins.Select(x => GhostVar(x.Name) + ":" + TypeString(AppType(x.Type)))));
        string rets = String.Join(", ", method.Outs.Select(x => GhostVar(x.Name) + ":" + TypeString(AppType(x.Type))));

        if (body != null)
        {
            foreach (Statement stmt in body.Body)
            {
                AddGhostStatement(stmt, null);
            }
            Action printStmts = () =>
            {
                string indent = "    ";
                foreach (RtlStmt s in stmts)
                {
                    RtlIndent rtlIndent = s as RtlIndent;
                    if (rtlIndent != null)
                    {
                        indent = rtlIndent.Positive ? indent + "    " : indent.Substring(4);
                        continue;
                    }
                    if (s.comment != null)
                    {
                        writer.WriteLine(indent + "// " + s.comment().Replace(Environment.NewLine, Environment.NewLine + indent));
                    }
                    if (s.ToString() != "")
                    {
                        writer.WriteLine(indent + s.ToString().Replace(Environment.NewLine, Environment.NewLine + indent));
                    }
                }
            };
            if (isRecursive)
            {
                Util.Assert(!isPrinting);
                string decreases = DecreasesExp(method);
                isPrinting = true;
                iwriter.WriteLine("function decreases_" + procName + "(" + parms + "):int { " + decreases + " }");
                isPrinting = false;
                string applyDecrease = "decreases_" + procName + "("
                                       + String.Join(", ", heapArgs.Concat(method.Ins.Select(x => GhostVar(x.Name)))) + ")";
                string sep = (method.Ins.Count + heapArgs.Count == 0) ? "" : ", ";
                CompileGhost("rec_" + procName, "__decreases:int" + sep + parms, rets,
                             "__decreases == " + applyDecrease, printStmts);
                CompileGhost(procName, parms, rets, null, () =>
                {
                    writer.WriteLine("    call " + String.Join(", ", method.Outs.Select(x => GhostVar(x.Name)))
                                     + (method.Outs.Count == 0 ? "" : " := ") + "rec_" + procName + "(" + applyDecrease
                                     + String.Concat(heapArgs.Concat(method.Ins.Select(x => GhostVar(x.Name)))
                                                     .Select(x => ", " + x)) + ");");
                });
            }
            else
            {
                CompileGhost(procName, parms, rets, null, printStmts);
            }
        }
        else if (isAxiom)
        {
            CompileGhost(procName, parms, rets, null, () => writer.WriteLine("    // dummy method body for axiom"));
        }
        else
        {
            CompileGhost(procName, parms, rets, null, null);
        }
    }
コード例 #26
0
 public static string SimpleName(string x)
 {
     return(DafnySpec.SimpleName(x));
 }
コード例 #27
0
ファイル: CompileField.cs プロジェクト: jango2015/Ironclad
 public CompileField(DafnySpec dafnySpec, Field field, TextWriter iwriter)
 {
     this.dafnySpec = dafnySpec;
     this.field = field;
     this.iwriter = iwriter;
 }
コード例 #28
0
ファイル: Compile.cs プロジェクト: jango2015/Ironclad
 public CompileBase(DafnySpec dafnySpec, TypeApply typeApply,
     TextWriter writer, TextWriter iwriter, string moduleName, List<string> imports)
 {
     this.dafnySpec = dafnySpec;
     this.typeApply = typeApply;
     this.writer = writer;
     this.iwriter = iwriter;
     this.moduleName = moduleName;
     this.imports = imports;
     this.visibleModules = imports.Concat(new List<string> { moduleName, "private##" + moduleName }).ToList();
 }