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 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 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"); } }
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("#")); }
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("#")); }
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"); } }
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 string GhostVar(string x, bool allowRename = true) { return((x == "INTERNAL_absMem") ? "$absMem" : "$ghost_" + (allowRename && renamer.ContainsKey(x) ? renamer[x] : "") + DafnySpec.CleanName(x)); }
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); }
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; }
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); } }
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 CompileField(DafnySpec dafnySpec, Field field, TextWriter iwriter) { this.dafnySpec = dafnySpec; this.field = field; this.iwriter = iwriter; }
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"); * } */ }
public bool IsArray(string x) { return(DafnySpec.IsArrayType(varTypes[x])); }
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; }
static Type ToType(Type t) { return(DafnySpec.ToType(t)); }
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"); } */ }
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 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 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 static string GhostProcName(string x) { return(DafnySpec.GhostProcName(x)); }
public static string FunName(string x) { return(DafnySpec.FunName(x)); }
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); } }
public static string SimpleName(string x) { return(DafnySpec.SimpleName(x)); }
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(); }