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); }
public Tuple <Function, TypeApply> GetSeqOperation(Type t, string op) { Function f = FindFunction(op); TypeApply tApp = Compile_SeqType((SeqType)t); return(Tuple.Create(f, Compile_Function(f, tApp.typeArgs))); }
public string GetSeqOperationName(Type t, string op) { TypeApply tApp = Compile_SeqType((SeqType)t); TypeApply fApp = Compile_Function(FindFunction(op), tApp.typeArgs); return(FunName(SimpleName(GetSeqOperation(t, op).Item2.AppName()))); }
public TypeApply Compile_Method(Method method, Dictionary <TypeParameter, Type> typeArgs) { Dictionary <string, TypeParameter> substArgs = new Dictionary <string, TypeParameter>(); method.TypeArgs.ForEach(t => substArgs.Add(t.Name, t)); typeArgs = typeArgs.ToDictionary(p => substArgs[p.Key.Name], p => p.Value); TypeApply apply = new TypeApply(this, method.FullSanitizedName, method.TypeArgs, typeArgs); if (!compileMethods.ContainsKey(apply)) { 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); }
public Tuple <Method, TypeApply> GetSeqMethod(Type t, string op) { Method m = FindMethod(op); TypeApply tApp = Compile_SeqType((SeqType)t); return(Tuple.Create(m, Compile_Method(m, tApp.typeArgs))); }
public override bool Equals(object obj) { TypeApply that = obj as TypeApply; if (that != null && that.name == this.name && that.typeArgs.Count == this.typeArgs.Count) { Dictionary <string, Type> thisArgs = this.typeArgs.ToDictionary(p => p.Key.ToString(), p => p.Value); Dictionary <string, Type> thatArgs = that.typeArgs.ToDictionary(p => p.Key.ToString(), p => p.Value); return(thatArgs.Keys.ToList().TrueForAll(x => thisArgs.ContainsKey(x) && thatArgs[x].Equals(thisArgs[x]))); } return(false); }
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); }
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(); }
public TypeApply Compile_Datatype(UserDefinedType t) { Dictionary <TypeParameter, Type> subst = new Dictionary <TypeParameter, Type>(); for (int i = 0; i < t.TypeArgs.Count; i++) { subst.Add(t.AsDatatype.TypeArgs[i], t.TypeArgs[i]); } TypeApply apply = new TypeApply(this, t.Name, t.AsDatatype.TypeArgs, subst); if (!compileDatatypes.ContainsKey(apply) && !Attributes.Contains(t.AsDatatype.Attributes, "imported")) { compileDatatypes.Add(apply, t); compileDatatypeList.Add(apply); AddDatatypeLemmas(t, apply); } return(apply); }
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 + " }"); } } }
public virtual Tuple <TextWriter, TextWriter, string, List <string> > ChooseWriter( Bpl.IToken tok, string name, TypeApply app = null) { string filename = Path.GetFullPath(tok.filename); if (app != null && !TrustedType(app.typeArgs.Values)) { throw new Exception("specification cannot refer to untrusted type: " + name); } if (IsSeqFile(filename, true)) { return(Tuple.Create(trustedWriter, (name.StartsWith("lemma_Seq") ? trustedWriter : trustedIWriter), "Trusted", new List <string>())); } else { return(ChooseOutDirWriter(filename)); } }
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; }
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; }
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 + " }"); } } }
public virtual Tuple<TextWriter,TextWriter,string,List<string>> ChooseWriter( Bpl.IToken tok, string name, TypeApply app = null) { string filename = Path.GetFullPath(tok.filename); if (app != null && !TrustedType(app.typeArgs.Values)) { throw new Exception("specification cannot refer to untrusted type: " + name); } if (IsSeqFile(filename, true)) { return Tuple.Create(trustedWriter, (name.StartsWith("lemma_Seq") ? trustedWriter : trustedIWriter), "Trusted", new List<string>()); } else { return ChooseOutDirWriter(filename); } }
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; }
public override void AddDatatypeLemmas(UserDefinedType t, TypeApply apply) { switch (t.Name) { case "Seq": { List<TypeApply> lemmaApps = new List<TypeApply>(); Dictionary<string,string> loopLemmas = new Dictionary<string,string>(); foreach (string lemmaName in seqLemmas) { Method lemma = FindMethod(lemmaName); var a = Compile_Method(lemma, apply.typeArgs); lemmaApps.Add(a); if (Attributes.Contains(lemma.Attributes, "loop_lemma")) { loopLemmas.Add(a.AppName(), ""); } } Type elementType = (t.TypeArgs.Count == 1) ? t.TypeArgs[0] : null; lemmaApps.ForEach(a => lemmas.Add(new LemmaCall("Seq", elementType, "call " + ProcName(true, SimpleName(a.AppName())) + "();", loopLemmas.ContainsKey(a.AppName())))); break; } } }
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; }
private void AddGhostCall(List<RtlVar> destVars, List<Expression> args, TypeApply typeApply, bool isHeap) { AddGhostCall(destVars, SimpleName(typeApply.AppName()), args, isHeap); }
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); }
public override Tuple<TextWriter,TextWriter,string,List<string>> ChooseWriter( Bpl.IToken tok, string name, TypeApply app = null) { string filename = Path.GetFullPath(tok.filename); bool trustedArg = (app != null && app.typeArgs.Count == 1 && TrustedType(app.typeArgs.Values)); if (IsSeqFile(filename, true)) { return Tuple.Create(trustedArg ? trustedWriter : checkedWriter, (name.StartsWith("lemma_Seq") ? (trustedArg ? trustedWriter : checkedWriter) : (trustedArg ? trustedIWriter : checkedIWriter)), trustedArg ? "Trusted" : "Checked", trustedArg ? new List<string>() : new List<string> { "Trusted" }); } else if (IsSeqFile(filename, false)) { return Tuple.Create(seqWriter, (name.StartsWith("lemma_Seq") ? seqWriter : seqIWriter), "Seq", new List<string> { "Trusted", "Checked", "Heap" }); } else { return ChooseOutDirWriter(filename); } }
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); } }
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)); }
public virtual void AddDatatypeLemmas(UserDefinedType t, TypeApply apply) { }
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; }
public TypeApply Compile_Datatype(UserDefinedType t) { Dictionary<TypeParameter,Type> subst = new Dictionary<TypeParameter,Type>(); for (int i = 0; i < t.TypeArgs.Count; i++) { subst.Add(t.AsDatatype.TypeArgs[i], t.TypeArgs[i]); } TypeApply apply = new TypeApply(this, t.Name, t.AsDatatype.TypeArgs, subst); if ( !compileDatatypes.ContainsKey(apply) && !Attributes.Contains(t.AsDatatype.Attributes, "imported")) { compileDatatypes.Add(apply, t); compileDatatypeList.Add(apply); AddDatatypeLemmas(t, apply); } return apply; }
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; }
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); }
private void AddGhostCall(List <RtlVar> destVars, List <Expression> args, TypeApply typeApply, bool isHeap) { AddGhostCall(destVars, SimpleName(typeApply.AppName()), args, isHeap); }
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("}"); }
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("}"); } } }
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(); }