Beispiel #1
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);
    }
Beispiel #2
0
    public void CompileDatatype1Ghost(Type t, TypeApply app, TextWriter writer, TextWriter iwriter)
    {
        // type List = Nil() | Cons(hd:int, tl:List);
        string dataName           = app.AppName(); // List
        List <DatatypeCtor> ctors = compileDatatypes[app].AsDatatype.Ctors;
        bool isSeq = dataName.StartsWith("Seq_");

        if (isSeq)
        {
            iwriter.WriteLine("type " + dataName + ";");
        }
        (isSeq ? writer : iwriter).WriteLine(
            "type " + (isSeq ? "implementation" : "") + "{:overload} " + dataName + " = "
            + String.Join(" | ", ctors.Select(c => Compile_Constructor(t, c.Name, app.typeArgs).AppName() + "("
                                              + String.Join(", ", c.Formals.Select(f => f.Name + ":" + TypeString(app.AppType(f.Type))))
                                              + ")")) + ";");

        if (isSeq)
        {
            foreach (var c in ctors)
            {
                string cName = Compile_Constructor(t, c.Name, app.typeArgs).AppName();
                string args  = String.Join(", ", c.Formals.Select(f => f.Name));
                string parms = String.Join(", ", c.Formals.Select(f => f.Name + ":"
                                                                  + TypeString(app.AppType(f.Type))));
                iwriter.WriteLine("function _" + cName + "(" + parms + "):" + dataName + ";");
                writer.WriteLine("function implementation _" + cName + "(" + parms + "):"
                                 + dataName + " { " + cName + "(" + args + ") }");
                foreach (var f in c.Formals)
                {
                    string tName = TypeString(app.AppType(f.Type));
                    iwriter.WriteLine("function " + f.Name + "_" + cName + "(x:" + dataName
                                      + "):" + tName + ";");
                    writer.WriteLine("function implementation " + f.Name + "_" + cName + "(x:" + dataName
                                     + "):" + tName + " { " + f.Name + "#" + cName + "(x) }");
                }
                iwriter.WriteLine("function is_" + cName + "(x:" + dataName + "):bool;");
                writer.WriteLine("function implementation is_" + cName + "(x:" + dataName
                                 + "):bool { x is " + cName + " }");
            }
        }
    }
Beispiel #3
0
    void CompileDatatype2(Type t, TypeApply app)
    {
        string dataName = app.AppName(); 
        string suffix = dataName.Substring(((UserDefinedType)t).Name.Length);
        bool isSeq = dataName.StartsWith("Seq_");
        string lemma = isSeq ? "call proc_Seq__Cons__All" + suffix + "();" : "";
        TextWriter iwriter = heapIWriter;
        List<DatatypeCtor> ctors = compileDatatypes[app].AsDatatype.Ctors;

        
        Func<string,string> dataIs = c => isSeq ? ("is_" + c + "(data)") : ("data is " + c);
        string tags = String.Join(" || ", ctors.Select(c =>
            "(r.regs[x] == Tag_" + dataName + "_" + c.Name + " && " + dataIs(
            Compile_Constructor(t, c.Name, app.typeArgs).AppName()) + ")"));
        iwriter.WriteLine(loadTagDecl(dataName, tags));
        heapWriter.WriteLine("implementation loadTag_" + dataName
            + "(my r_old:regs, const my core_state:core_state, const linear stk:mem, const linear statics:mem, const linear io:IOState, linear mems_old:mems, $commonVars:commonVars, $gcVars:gcVars, $toAbs:[int]int, $absMem:[int][int]int, $stacksFrames:[int]Frames, objLayouts:[int]ObjLayout, heap:Heap, x:int, y:opn_mem, data:"
            + dataName + ", abs:int, obj:int)");
        heapWriter.WriteLine("  returns(my r:regs, linear mems:mems)");
        heapWriter.WriteLine("{");
        heapWriter.WriteLine("  assert THeapValue(objLayouts, true, $toAbs, obj, abs);");
        heapWriter.WriteLine("  assert THeapInv($absMem, objLayouts, heap);");
        heapWriter.WriteLine("  " + lemma);
        heapWriter.WriteLine("  call r, mems := gcLoadField(r_old, core_state, stk, statics, io, mems_old,");
        heapWriter.WriteLine("    $commonVars, $gcVars, $absMem, $toAbs, $stacksFrames, objLayouts,");
        heapWriter.WriteLine("    x, y, obj - 4, 2);");
        heapWriter.WriteLine("}");

        foreach (var ctor in ctors)
        {
            var ints = ctor.Formals.Where(x => !IsPtrType(app.AppType(x.Type))).ToList();
            var ptrs = ctor.Formals.Where(x =>  IsPtrType(app.AppType(x.Type))).ToList();
            var sorted = ints.Concat(ptrs).ToList();
            string ctorName = Compile_Constructor(t, ctor.Name, app.typeArgs).AppName();
            string cons = isSeq ? ("_" + ctorName) : ctorName;

            
            string parms = String.Join(", ", ctor.Formals.Select(
                c => "arg_" + c.Name + ":" + TypeString(app.AppType(c.Type))));
            
            string args = String.Join(", ", ctor.Formals.Select(c => "arg_" + c.Name));
            int argRetSize = 4 + 4 * Math.Max(ints.Count, ptrs.Count);
            heapIWriter.WriteLine("const stack_size__DafnyCC__Proc_Alloc_" + ctorName + ":int := 256;");
            iwriter.WriteLine(allocDecl1(
                                         dataName,
                                         ctorName,
                                         cons,
                                         parms,
                                         args,
                                         argRetSize.ToString()));
            string triggers = (IPSize == 8) ? String.Format("{0} && {1}", GcTO64(1), GcTO(3)) : GcTO(1);
            for (int i = 0; i < ints.Count; i++)
            {
                
                string val = "stk_old.map[r_old.regs[ESP] + "
                    + (IPSize + 4 * i) + "]";
                iwriter.WriteLine("requires " + CompileBase.IntEqTyped(app.AppType(ints[i].Type), "arg_" + ints[i].Name, val) + ";");
                triggers += String.Format(" && {0}", (IPSize == 8 ? StackTO64(i + 1): StackTO(i + 1)));
            }
            for (int i = 0; i < ptrs.Count; i++)
            {
                
                iwriter.WriteLine("requires StackAbsSlot(heap_old, $stacksFrames_old, r_old.regs[ESP] + "
                    + (IPSize + 4 + 4 * i) + " + stackGcOffset) == Abs_" + TypeString(app.AppType(ptrs[i].Type))
                    + "(arg_" + ptrs[i].Name + ");");
                triggers += String.Format(" && {0}", (IPSize == 8 ? GcTO64(i + 2): GcTO(i + 2)));
            }
            iwriter.WriteLine(allocDecl2(
                                         dataName,
                                         cons,
                                         PreserveHeap(minVerify),
                                         args));
            heapWriter.WriteLine(allocImpl1(
                                            dataName,
                                            ctor.Name,
                                            ctorName,
                                            cons,
                                            parms,
                                            args,
                                            (12 + 4 * sorted.Count).ToString(),
                                            (12 + 4 * ints.Count).ToString(),
                                            triggers,
                                            lemma));
            for (int i = 0; i < ints.Count; i++)
            {
                heapWriter.WriteLine(allocImplInt(
                                                  dataName,
                                                  ctorName,
                                                  ints[i].Name,
                                                  (12 + IPSize + 4 * i).ToString()));
            }
            for (int i = 0; i < ptrs.Count; i++)
            {
                heapWriter.WriteLine(allocImplPtr(
                                                  dataName,
                                                  ctorName,
                                                  ptrs[i].Name,
                                                  (RegAlloc.stackGcOffset + 16 + IPSize + 4 * i).ToString() + "/* stackGcOffset + 16 + IPSize + " + (4 * i) + " */"));
            }
            heapWriter.WriteLine(allocImpl2(
                                            dataName,
                                            ctorName,
                                            (RegAlloc.stackGcOffset + 12 + IPSize).ToString() + "/* stackGcOffset + 12 + IPSize */"));

            for (int i = 0; i < sorted.Count; i++)
            {
                var formal = sorted[i];
                iwriter.WriteLine(loadField(
                                            dataName,
                                            dataIs(ctorName),
                                            formal.Name));
                if (IsPtrType(app.AppType(formal.Type)))
                {
                    
                    
                    iwriter.WriteLine("ensures  HeapAbsData(heap, $absMem_old[abs]["
                        + (3 + i) + "]) == Abs_" + TypeString(app.AppType(formal.Type))
                        + "(" + formal.Name + (isSeq ? "_" : "#") + ctorName + "(data));");
                    iwriter.WriteLine("ensures  HeapValue(objLayouts_old, true, $toAbs_old, r.regs[x], $absMem_old[abs]["
                        + (3 + i) + "]);");
                    if (DafnySpec.IsArrayType(app.AppType(formal.Type)))
                    {
                        iwriter.WriteLine("ensures  $absMem_old[abs][" + (3+i) + "] == " + formal.Name + "#" + ctorName + "(data).arrAbs;");
                    }
                }
                else
                {
                    
                    iwriter.WriteLine("ensures  " + CompileBase.IntEqTyped(
                        app.AppType(formal.Type), formal.Name + (isSeq ? "_" : "#") + ctorName + "(data)", "r.regs[x]")
                        + ";");
                }
                heapWriter.WriteLine("implementation loadField_" + dataName + "_" + formal.Name
                    + "(my r_old:regs, const my core_state:core_state, const linear stk:mem, const linear statics:mem, const linear io:IOState, linear mems_old:mems, $commonVars:commonVars, $gcVars:gcVars, $toAbs:[int]int, $absMem:[int][int]int, $stacksFrames:[int]Frames, objLayouts:[int]ObjLayout, heap:Heap, x:int, y:opn_mem, data:"
                    + dataName + ", abs:int, obj:int)");
                heapWriter.WriteLine("    returns(my r:regs, linear mems:mems)");
                heapWriter.WriteLine("{");
                heapWriter.WriteLine("    assert THeapValue(objLayouts, true, $toAbs, obj, abs);");
                heapWriter.WriteLine("    assert THeapInv($absMem, objLayouts, heap);");
                heapWriter.WriteLine("    call r, mems := gcLoadField(r_old, core_state, stk, statics, io, mems_old, $commonVars, $gcVars, $absMem, $toAbs, $stacksFrames, objLayouts,");
                heapWriter.WriteLine("        x, y, obj - 4, " + (3 + i) + ");");
                heapWriter.WriteLine("    assert THeapValue(objLayouts, true, $toAbs, r.regs[x], $absMem[abs][" + (3 + i) + "]);");
                heapWriter.WriteLine("}");
            }
        }
    }
Beispiel #4
0
    void CompileDatatype1(Type t, TypeApply app)
    {
        
        string dataName = app.AppName(); 
        List<DatatypeCtor> ctors = compileDatatypes[app].AsDatatype.Ctors;
        bool isSeq = dataName.StartsWith("Seq_");
        bool isTrusted = isSeq ? TrustedType(app.typeArgs.Values) : TrustedType(t);

        CompileDatatype1Ghost(t, app,
            isTrusted ? trustedWriter : checkedWriter,
            isTrusted ? trustedIWriter : checkedIWriter);
        CompileDatatype1Code(t, app);
    }
Beispiel #5
0
    void CompileDatatype1Code(Type t, TypeApply app)
    {
        
        string dataName = app.AppName(); 
        List<DatatypeCtor> ctors = compileDatatypes[app].AsDatatype.Ctors;
        bool isSeq = dataName.StartsWith("Seq_");

        
        
        for (int i = 0; i < ctors.Count; i++)
        {
            heapIWriter.WriteLine("const Tag_" + dataName + "_" + ctors[i].Name + ":int := " + (i + 1) + ";");
        }

        
        
        
        
        
        
        heapWriter.WriteLine("function HeapWordInv_" + dataName + "(absData:[int]AbsData, objLayout:ObjLayout, wordMem:[int]int, data:" + dataName + "):bool");
        heapWriter.WriteLine("{");
        heapWriter.WriteLine("    true");

        foreach (var ctor in ctors)
        {
            var ints = ctor.Formals.Where(x => !IsPtrType(app.AppType(x.Type))).ToList();
            var ptrs = ctor.Formals.Where(x =>  IsPtrType(app.AppType(x.Type))).ToList();
            var sorted = ints.Concat(ptrs).ToList();
            string ctorName = Compile_Constructor(t, ctor.Name, app.typeArgs).AppName();

            
            
            string wordMems = "";
            for (int i = 0; i < sorted.Count; i++)
            {
                heapIWriter.WriteLine("const Offset_" + dataName + "_" + sorted[i].Name + ":int := " + (8 + 4 * i) + ";");
                if (IsPtrType(app.AppType(sorted[i].Type)))
                {
                    wordMems += " && absData[wordMem[" + (3 + i) + "]] == Abs_"
                        + TypeString(app.AppType(sorted[i].Type)) + "(" + sorted[i].Name
                        + (isSeq ? "_" : "#") + ctorName + "(data))";
                }
                else
                {
                    wordMems += " && " + CompileBase.IntEqTyped(
                        app.AppType(sorted[i].Type),
                        sorted[i].Name + (isSeq ? "_" : "#") + ctorName + "(data)",
                        "wordMem[" + (3 + i) + "]");
                }
            }

            
            string dataIs = isSeq ? ("is_" + ctorName + "(data)") : "data is " + ctorName;
            heapWriter.WriteLine("&& (" + dataIs + " ==> objLayout == ObjLayout("
                + (3 + sorted.Count) + ", " + (3 + ints.Count)
                + ") && wordMem[2] == Tag_" + dataName + "_" + ctor.Name + wordMems + ")");
        }

        heapWriter.WriteLine("}");
    }
Beispiel #6
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;
 }
Beispiel #7
0
    public void CompileDatatype1Ghost(Type t, TypeApply app, TextWriter writer, TextWriter iwriter)
    {
        // type List = Nil() | Cons(hd:int, tl:List);
        string dataName = app.AppName(); // List
        List<DatatypeCtor> ctors = compileDatatypes[app].AsDatatype.Ctors;
        bool isSeq = dataName.StartsWith("Seq_");
        if (isSeq)
        {
            iwriter.WriteLine("type " + dataName + ";");
        }
        (isSeq ? writer : iwriter).WriteLine(
            "type " + (isSeq ? "implementation" : "") + "{:overload} " + dataName + " = "
            + String.Join(" | ", ctors.Select(c => Compile_Constructor(t, c.Name, app.typeArgs).AppName() + "("
                + String.Join(", ", c.Formals.Select(f => f.Name + ":" + TypeString(app.AppType(f.Type))))
                + ")")) + ";");

        if (isSeq)
        {
            foreach (var c in ctors)
            {
                string cName = Compile_Constructor(t, c.Name, app.typeArgs).AppName();
                string args = String.Join(", ", c.Formals.Select(f => f.Name));
                string parms = String.Join(", ", c.Formals.Select(f => f.Name + ":" 
                    + TypeString(app.AppType(f.Type))));
                iwriter.WriteLine("function _" + cName + "(" + parms + "):" + dataName + ";");
                writer.WriteLine("function implementation _" + cName + "(" + parms + "):"
                    + dataName + " { " + cName + "(" + args + ") }");
                foreach (var f in c.Formals)
                {
                    string tName = TypeString(app.AppType(f.Type));
                    iwriter.WriteLine("function " + f.Name + "_" + cName + "(x:" + dataName
                        + "):" + tName + ";");
                    writer.WriteLine("function implementation " + f.Name + "_" + cName + "(x:" + dataName
                        + "):" + tName + " { " + f.Name + "#" + cName + "(x) }");
                }
                iwriter.WriteLine("function is_" + cName + "(x:" + dataName + "):bool;");
                writer.WriteLine("function implementation is_" + cName + "(x:" + dataName
                    + "):bool { x is " + cName + " }");
            }
        }
    }
Beispiel #8
0
 private void AddGhostCall(List <RtlVar> destVars, List <Expression> args, TypeApply typeApply, bool isHeap)
 {
     AddGhostCall(destVars, SimpleName(typeApply.AppName()), args, isHeap);
 }
Beispiel #9
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);
        }
    }
Beispiel #10
0
 private void AddGhostCall(List<RtlVar> destVars, List<Expression> args, TypeApply typeApply, bool isHeap)
 {
     AddGhostCall(destVars, SimpleName(typeApply.AppName()), args, isHeap);
 }