public CompilerResults Compile() { var exitval = DafnyDriver.ProcessCommandLineArguments(CompilationArgs, out var dafnyFiles, out var otherFiles); if (!PerformPreliminaryChecks(exitval, out var errorneousCompileResults)) { return(errorneousCompileResults); } TextWriter tw = new StringWriter(); Type.ResetScopes(); int oldErrorCount = Dp.reporter.Count(ErrorLevel.Error); DafnyDriver.CompileDafnyProgram(Dp, Path, otherFiles.AsReadOnly(), true, tw); int newErrorCount = Dp.reporter.Count(ErrorLevel.Error); if (oldErrorCount != newErrorCount) { return(ExtractError(oldErrorCount)); } bool hasMain = new Microsoft.Dafny.CsharpCompiler(Dp.reporter).HasMain(Dp, out _); return(new CompilerResults { Error = false, Executable = hasMain, Message = tw.ToString().TrimEnd('\r', '\n') }); }
public Type AppType(Type t) { Util.Assert(t != null); return(Resolver.SubstType(t, typeArgs)); }
public void AddTypeWellFormed(List <RtlExp> specs, RtlExp exp, bool isGhost, Type t, List <UserDefinedType> recs) { UserDefinedType ut = t as UserDefinedType; if (minVerify && !isGhost && t is IntType) { specs.Add(new RtlApply("word", new RtlExp[] { exp })); return; } if (t is NatType) { specs.Add(new RtlBinary(">=", exp, new RtlInt(0))); } if (ut != null && ut.AsDatatype != null && recs.TrueForAll(r => ut.Name != r.Name) ) { recs.Add(ut); foreach (var ctor in ut.AsDatatype.Ctors) { List <RtlExp> cspecs = new List <RtlExp>(); foreach (var f in ctor.Formals) { AddTypeWellFormed(cspecs, new RtlLiteral(f.Name + "#" + ctor.Name + "(" + exp + ")"), isGhost, f.Type, recs); } foreach (var spec in cspecs) { specs.Add(new RtlLiteral("((" + exp + ") is " + ctor.Name + " ==> (" + spec + "))")); } } recs.RemoveAt(recs.Count - 1); } }
public static string IntToTyped(Type t, string e) { return ((t is BoolType) ? "((" + e + ") != 0)" : (t is RealType) ? "(real(" + e + "))" : e); }
public Type AppType(Type t) { Util.Assert(t != null); return Resolver.SubstType(t, typeArgs); }
public LemmaCall(string module, Type type, string stmt, bool loopLemma) { this.module = module; this.type = type; this.stmt = stmt; this.loopLemma = loopLemma; }
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 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 Type StartTypeArg(Attributes attrs) { Type prev = DafnySpec.defaultPolyType; for (var a = attrs; a != null; a = a.Prev) { if (a.Name == "typearg") { string s = a.Args[0].S; switch (s) { case "int": DafnySpec.defaultPolyType = Type.Int; break; case "bool": DafnySpec.defaultPolyType = Type.Bool; break; case "real": DafnySpec.defaultPolyType = Type.Real; break; default: if (typeApply.typeSubsts.ContainsKey(s)) { DafnySpec.defaultPolyType = typeApply.typeSubsts[s]; } else { throw new Exception("not implemented: StartTypeArg: " + s); } break; } break; } } return(prev); }
public void AddGhostStatement(Statement stmt) { Util.Assert(!isPrinting); stmts.Add(new RtlComment("###LINE: " + stmt.Tok.filename + ": " + stmt.Tok.line)); List <Statement> resolved = ResolveStmt(stmt); if (resolved != null) { UpdateStmt u = stmt as UpdateStmt; if (u != null) { Type oldDefault = StartTypeArg(u.Rhss[0].Attributes); resolved.ForEach(AddGhostStatement); DafnySpec.defaultPolyType = oldDefault; } else { resolved.ForEach(AddGhostStatement); } } else { AddResolvedGhostStatement(stmt); } }
public RtlExp GhostExpression(Expression exp, bool inRecSpec = false, bool inRequiresOrOld = false, Attributes attrs = null) { Type oldDefault = StartTypeArg(attrs); var e = GhostExpressionRec(exp, inRecSpec, inRequiresOrOld); DafnySpec.defaultPolyType = oldDefault; return(e); }
public static IdentifierExpr MakeIdentifierExpr(string name, Type type, bool isGhost) { Util.Assert(type != null); IdentifierExpr id = new IdentifierExpr(Bpl.Token.NoToken, name); id.Type = type; id.Var = new LocalVariable(Bpl.Token.NoToken, Bpl.Token.NoToken, name, type, isGhost); return(id); }
// REVIEW: is this receiving the correct typeArgs? public TypeApply Compile_Constructor(Type t, string constructor, Dictionary <TypeParameter, Type> typeArgs) { UserDefinedType ut = (UserDefinedType)t; Dictionary <string, TypeParameter> substArgs = new Dictionary <string, TypeParameter>(); ut.AsDatatype.TypeArgs.ForEach(tt => substArgs.Add(tt.Name, tt)); typeArgs = typeArgs.ToDictionary(p => substArgs[p.Key.Name], p => p.Value); return(new TypeApply(this, constructor, ut.AsDatatype.TypeArgs, typeArgs)); }
private void IsDatatype(Statement st, ref List <Solution> solution_list) { List <Expression> call_arguments = null; IVariable lv = null; IVariable declaration = null; Dafny.LiteralExpr lit = null; Dafny.Type type = null; InitArgs(st, out lv, out call_arguments); Contract.Assert(tcce.OfSize(call_arguments, 1), Util.Error.MkErr(st, 0, 1, call_arguments.Count)); NameSegment argument = call_arguments[0] as NameSegment; Contract.Assert(argument != null, Util.Error.MkErr(st, 1, typeof(NameSegment))); declaration = GetLocalValueByName(argument) as IVariable; Contract.Assert(declaration != null, Util.Error.MkErr(st, 1, typeof(IVariable))); if (declaration.Type == null) { type = globalContext.GetVariableType(declaration.Name); } else { type = declaration.Type; } // type of the argument is unknown thus it's not a datatype if (type != null && type.IsDatatype) { lit = new Dafny.LiteralExpr(st.Tok, true); } else { // check if the argument is a nested data type Dafny.UserDefinedType udt = type as Dafny.UserDefinedType; if (udt != null) { if (globalContext.datatypes.ContainsKey(udt.Name)) { lit = new Dafny.LiteralExpr(st.Tok, true); } else { lit = new Dafny.LiteralExpr(st.Tok, false); } } else { lit = new Dafny.LiteralExpr(st.Tok, false); } } Contract.Assert(lit != null); localContext.AddLocal(lv, lit); }
public string TypeString(Type t) { t = ToType(t); MapType mt = t as MapType; UserDefinedType ut = t as UserDefinedType; SeqType seq = t as SeqType; if (t is BoolType) { return("bool"); } else if (t is IntType) { return("int"); } else if (t is RealType) { return("real"); } else if (mt != null) { return("[" + TypeString(mt.Domain) + "]" + TypeString(mt.Range)); } else if (ut != null && ut.AsDatatype != null) { return(Compile_Datatype(ut).AppName()); } else if (ut != null && ut.Name == "array") { if (!(ToType(ut.TypeArgs[0]) is IntType) || ToType(ut.TypeArgs[0]) is NatType) { throw new Exception("not implemented: arrays of non-int types: " + ToType(ut.TypeArgs[0])); } return("ArrayOfInt"); } else if (ut != null && ut.Name == "INTERNAL_AbsMem") { return("[int][int]int"); } else if (ut != null && ut.Name == "INTERNAL_ArrayElems") { return("[int]int"); } else if (ut != null && !ut.IsTypeParameter) { return(ut.Name); } else if (seq != null) { return(Compile_SeqType(seq).AppName()); } else { throw new Exception("not implemented: " + t + ": " + t.GetType()); } }
public static BinaryExpr MakeBinaryExpr(BinaryExpr.Opcode op, BinaryExpr.ResolvedOpcode rop, Type t, Expression e0, Expression e1) { Util.Assert(t != null && e0.Type != null && e1.Type != null); BinaryExpr e = new BinaryExpr(e0.tok, op, e0, e1); e.ResolvedOp = rop; e.Type = t; return(e); }
//- Assert that et is a well-formed value of type t, represented by integer ei public static RtlExp IntEqTyped(Type t, RtlExp et, RtlExp ei) { return ((t is BoolType) ? new RtlBinary("||", new RtlBinary("&&", et, new RtlBinary("==", ei, new RtlInt(1))), new RtlBinary("&&", new RtlApply("!", new RtlExp[] { et }), new RtlBinary("==", ei, new RtlInt(0)))) : (t is RealType) ? new RtlBinary("==", et, new RtlApply("real", new RtlExp[] { ei })) : new RtlBinary("==", et, ei)); }
public static Microsoft.Dafny.Type[] getTypes(List <Microsoft.Dafny.Expression> expressions) { Microsoft.Dafny.Type[] Types = new Microsoft.Dafny.Type[expressions.Count]; int index = 0; foreach (var x in expressions) { Types[index++] = x.Type; } return(Types); }
public RtlVar TempVar(Type t, bool declare = true) { string name = "$ghost__" + TempName(); RtlVar ret = new RtlVar(name, false, AppType(t)); if (declare) { allVars.Add(name, ret); } return(ret); }
public void AddGhostVarDecl(string varName, Type t, bool isGhost) { string name = GhostVar(varName); if (allVars.ContainsKey(name) || forallVars.Exists(d => d.ContainsKey(name))) { AddRename(varName); name = GhostVar(varName); } var dict = (forallVars.Count == 0) ? allVars : forallVars[forallVars.Count - 1]; dict.Add(name, new RtlVar(name, isGhost, AppType(t))); }
static void FrameExprRegions(FrameExpression fe, List <IdRegion> regions, bool descendIntoExpressions, ModuleDefinition module) { Contract.Requires(fe != null); Contract.Requires(regions != null); if (descendIntoExpressions) { ExprRegions(fe.E, regions, module); } if (fe.Field != null) { Microsoft.Dafny.Type showType = null; // TODO: if we had the instantiated type of this field, that would have been nice to use here (but the Resolver currently does not compute or store the instantiated type for a FrameExpression) IdRegion.Add(regions, fe.tok, fe.Field, showType, "field", false, module); } }
public static Type ToType(Type t) { TypeProxy proxy = t as TypeProxy; if (proxy != null && proxy.T == null) { return(defaultPolyType); //- pick arbitrary type } if (proxy != null) { return(ToType(proxy.T)); } return(t); }
public static Type ToType(Type t) { TypeProxy proxy = t as TypeProxy; if (proxy != null && proxy.T == null) { Util.Assert(false); // Dafny appears to be doing sane type resolution now return(defaultPolyType); //- pick arbitrary type } if (proxy != null) { return(ToType(proxy.T)); } return(t); }
void FrameExprRegions(FrameExpression fe, List <IdRegion> regions, bool descendIntoExpressions, Microsoft.Dafny.Program prog, ModuleDefinition module) { Contract.Requires(fe != null); Contract.Requires(regions != null); Contract.Requires(prog != null); if (descendIntoExpressions) { ExprRegions(fe.E, regions, prog, module); } if (fe.Field != null) { Microsoft.Dafny.Type showType = null; // TODO: if we had the instantiated type of this field, that would have been nice to use here (but the Resolver currently does not compute or store the instantiated type for a FrameExpression) var kind = !(fe.Field is ConstantField) ? "field" : fe.Field.IsStatic && !(fe.Field.EnclosingClass is DefaultClassDecl) ? "static const" : "const"; IdRegion.Add(regions, prog, fe.tok, fe.Field, showType, kind, false, module); RecordUseAndDef(prog, fe.tok, fe.Field.Name.Length, fe.Field.tok); } }
private IdRegion(Bpl.IToken tok, Field decl, Microsoft.Dafny.Type showType, string kind, bool isDefinition, ModuleDefinition context) { Contract.Requires(tok != null); Contract.Requires(decl != null); Contract.Requires(kind != null); if (showType == null) { showType = decl.Type; } Start = tok.pos; Length = decl.Name.Length; HoverText = string.Format("({4}{2}{3}) {0}: {1}", decl.FullNameInContext(context), showType.TypeName(context), decl.IsGhost ? "ghost " : "", kind, decl.IsUserMutable || decl is DatatypeDestructor ? "" : decl.IsMutable ? " non-assignable " : "immutable "); Kind = !isDefinition ? OccurrenceKind.Use : OccurrenceKind.Definition; }
public bool TrustedType(Type t) { SeqType seq = t as SeqType; UserDefinedType ut = t as UserDefinedType; if (seq != null) { return(TrustedType(seq.Arg)); } else if (ut != null) { return(IsSpecFile(ut.AsDatatype.tok.filename) && TrustedType(ut.TypeArgs)); } else { return(true); } }
private IdRegion(Bpl.IToken tok, Field decl, Microsoft.Dafny.Type showType, string kind, bool isDefinition, ModuleDefinition context) { Contract.Requires(tok != null); Contract.Requires(decl != null); Contract.Requires(kind != null); if (showType == null) { showType = decl.Type; } Start = tok.pos; Length = decl.Name.Length; var name = decl.EnclosingClass != null && !(decl.EnclosingClass is DefaultClassDecl) ? decl.FullNameInContext(context) : decl.Name; // some built-in members like "Keys" may not have an .EnclosingClass HoverText = string.Format("({4}{2}{3}) {0}: {1}", name, showType.TypeName(context), decl.IsGhost ? "ghost " : "", kind, decl.IsUserMutable || decl is ConstantField || decl is DatatypeDestructor ? "" : decl.IsMutable ? " non-assignable " : "immutable "); Kind = !isDefinition ? OccurrenceKind.Use : OccurrenceKind.Definition; }
public TypeApply Compile_Constructor(Type t, string constructor, List <Type> dataTypeArgs, Dictionary <TypeParameter, Type> typeArgs) { UserDefinedType ut = (UserDefinedType)t; if (dataTypeArgs == null) { dataTypeArgs = ut.TypeArgs; } Util.Assert(ut.AsDatatype.TypeArgs.Count == dataTypeArgs.Count); Dictionary <TypeParameter, Type> typeMap = new Dictionary <TypeParameter, Type>(); for (int i = 0; i < dataTypeArgs.Count; i++) { typeMap.Add(ut.AsDatatype.TypeArgs[i], Resolver.SubstType(dataTypeArgs[i], typeArgs)); } return(new TypeApply(this, constructor, ut.AsDatatype.TypeArgs, typeMap)); }
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 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 Type AppType(Type t) { return typeApply.AppType(t); }
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("}"); } } }
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("}"); }
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 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 TypeApply Compile_Constructor(Type t, string constructor, List<Type> dataTypeArgs, Dictionary<TypeParameter,Type> typeArgs) { UserDefinedType ut = (UserDefinedType) t; if (dataTypeArgs == null) { dataTypeArgs = ut.TypeArgs; } Util.Assert(ut.AsDatatype.TypeArgs.Count == dataTypeArgs.Count); Dictionary<TypeParameter,Type> typeMap = new Dictionary<TypeParameter,Type>(); for (int i = 0; i < dataTypeArgs.Count; i++) { typeMap.Add(ut.AsDatatype.TypeArgs[i], Resolver.SubstType(dataTypeArgs[i], typeArgs)); } return new TypeApply(this, constructor, ut.AsDatatype.TypeArgs, typeMap); }
public bool TrustedType(Type t) { SeqType seq = t as SeqType; UserDefinedType ut = t as UserDefinedType; if (seq != null) { return TrustedType(seq.Arg); } else if (ut != null) { return IsSpecFile(ut.AsDatatype.tok.filename) && TrustedType(ut.TypeArgs); } else { return true; } }
public RtlVar TempVar(Type t, bool declare = true) { string name = "$ghost__" + TempName(); RtlVar ret = new RtlVar(name, false, AppType(t)); if (declare) { allVars.Add(name, ret); } return ret; }
static Type ToType(Type t) { return DafnySpec.ToType(t); }
public void AddTypeWellFormed(List<RtlExp> specs, RtlExp exp, bool isGhost, Type t, List<UserDefinedType> recs) { UserDefinedType ut = t as UserDefinedType; if (minVerify && !isGhost && t is IntType) { specs.Add(new RtlApply("word", new RtlExp[] { exp })); return; } if (t is NatType) { specs.Add(new RtlBinary(">=", exp, new RtlInt(0))); } if (ut != null && ut.AsDatatype != null && recs.TrueForAll(r => ut.Name != r.Name) ) { recs.Add(ut); foreach (var ctor in ut.AsDatatype.Ctors) { List<RtlExp> cspecs = new List<RtlExp>(); foreach (var f in ctor.Formals) { AddTypeWellFormed(cspecs, new RtlLiteral(f.Name + "#" + ctor.Name + "(" + exp + ")"), isGhost, f.Type, recs); } foreach (var spec in cspecs) { specs.Add(new RtlLiteral("((" + exp + ") is " + ctor.Name + " ==> (" + spec + "))")); } } recs.RemoveAt(recs.Count - 1); } }
public string TypeString(Type t) { t = ToType(t); MapType mt = t as MapType; UserDefinedType ut = t as UserDefinedType; SeqType seq = t as SeqType; if (t is BoolType) { return "bool"; } else if (t is IntType) { return "int"; } else if (t is RealType) { return "real"; } else if (mt != null) { return "[" + TypeString(mt.Domain) + "]" + TypeString(mt.Range); } else if (ut != null && ut.AsDatatype != null) { return Compile_Datatype(ut).AppName(); } else if (ut != null && ut.Name == "array") { if (!(ToType(ut.TypeArgs[0]) is IntType) || ToType(ut.TypeArgs[0]) is NatType) { throw new Exception("not implemented: arrays of non-int types: " + ToType(ut.TypeArgs[0])); } return "ArrayOfInt"; } else if (ut != null && ut.Name == "INTERNAL_AbsMem") { return "[int][int]int"; } else if (ut != null && ut.Name == "INTERNAL_ArrayElems") { return "[int]int"; } else if (ut != null && !ut.IsTypeParameter) { return ut.Name; } else if (seq != null) { return Compile_SeqType(seq).AppName(); } else { throw new Exception("not implemented: " + t + ": " + t.GetType()); } }
public static string IntToTyped(Type t, string e) { return (t is BoolType) ? "((" + e + ") != 0)" : (t is RealType) ? "(real(" + e + "))" : e; }
public static string IntEqTyped(Type t, string et, string ei) { return "(" + IntEqTyped(t, new RtlLiteral(et), new RtlLiteral(ei)) + ")"; }
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 + " }"); } } }
//- Assert that et is a well-formed value of type t, represented by integer ei public static RtlExp IntEqTyped(Type t, RtlExp et, RtlExp ei) { return (t is BoolType) ? new RtlBinary("||", new RtlBinary("&&", et, new RtlBinary("==", ei, new RtlInt(1))), new RtlBinary("&&", new RtlApply("!", new RtlExp[] { et }), new RtlBinary("==", ei, new RtlInt(0)))) : (t is RealType) ? new RtlBinary("==", et, new RtlApply("real", new RtlExp[] { ei })) : new RtlBinary("==", et, ei); }
// REVIEW: is this receiving the correct typeArgs? public TypeApply Compile_Constructor(Type t, string constructor, Dictionary<TypeParameter,Type> typeArgs) { UserDefinedType ut = (UserDefinedType) t; Dictionary<string,TypeParameter> substArgs = new Dictionary<string,TypeParameter>(); ut.AsDatatype.TypeArgs.ForEach(tt => substArgs.Add(tt.Name, tt)); typeArgs = typeArgs.ToDictionary(p => substArgs[p.Key.Name], p => p.Value); return new TypeApply(this, constructor, ut.AsDatatype.TypeArgs, typeArgs); }
public string TypeString(Type t) { return dafnySpec.TypeString(t); }
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 static IdentifierExpr MakeIdentifierExpr(string name, Type type, bool isGhost) { Util.Assert(type != null); IdentifierExpr id = new IdentifierExpr(Bpl.Token.NoToken, name); id.Type = type; id.Var = new LocalVariable(Bpl.Token.NoToken, Bpl.Token.NoToken, name, type, isGhost); return id; }
public Tuple<Method,TypeApply> GetSeqBuildMethod(Type t, SeqTree tree, List<bool> elemDimensions) { if (elemDimensions.Count == 0) { return GetSeqMethod(t, "seq_Empty"); } if (elemDimensions.Count == 2 && elemDimensions[0] && elemDimensions[1]) { return GetSeqMethod(t, "seq_Append"); } string op = "seq_" + SeqTree.TreeName(tree); DatatypeDecl seqDecl = FindDatatype("Seq"); var tok = new Bpl.Token(0, 0); tok.filename = @"!\Seq.dfy"; TypeApply tApp = Compile_SeqType((SeqType)t); Type dataType = new UserDefinedType(tok, "Seq", seqDecl, new List<Type> { ((SeqType)t).Arg }); Type elemType = ((SeqType)t).Arg; Func<string,Type,Expression> idExpr = (x, typ) => { var e = new IdentifierExpr(tok, x); e.Type = typ; e.Var = new LocalVariable(tok, tok, x, typ, false); return e; }; Func<string,List<Expression>,FunctionCallExpr> seqCall = (x, args) => { var seqOp = GetSeqOperation(t, x); FunctionCallExpr callExpr = new FunctionCallExpr( tok, "Seq_Empty", new ThisExpr(tok), tok, args); callExpr.Function = seqOp.Item1; callExpr.TypeArgumentSubstitutions = seqOp.Item2.typeArgs; return callExpr; }; Expression empty = seqCall("Seq_Empty", new List<Expression> {}); int varCount = 0; Func<SeqTree,Expression> resultRec = null; resultRec = (subtree) => { if (subtree == null) { return idExpr("s" + (varCount++), dataType); } if (subtree.buildCount >= 0) { Expression build = empty; for (int i = 0; i < subtree.buildCount; i++) { build = seqCall("Seq_Build", new List<Expression> { build, idExpr("a" + (varCount++), elemType) }); } return build; } else { return seqCall("Seq_Append", new List<Expression> { resultRec(subtree.left), resultRec(subtree.right) }); } }; Expression result = resultRec(tree); Expression post = seqCall("Seq_Equal", new List<Expression> { idExpr("s", dataType), result }); List<Statement> stmts = new List<Statement>(); for (int i = elemDimensions.Count; i > 0;) { bool isFirst = (i == elemDimensions.Count); i--; if (elemDimensions[i]) { if (isFirst) { stmts.Add(new AssignStmt(tok, tok, idExpr("s", dataType), new ExprRhs(idExpr("s" + i, dataType)))); } else { // s := seq_Append(s9, s); var selectExpr = new MemberSelectExpr(tok, new ThisExpr(tok), "seq_Append"); selectExpr.Member = FindMethod(selectExpr.MemberName); // Manually resolve here selectExpr.TypeApplication = new List<Type>() { elemType }; // Manually resolve here selectExpr.Type = new InferredTypeProxy(); // Manually resolve here CallStmt callStmt = new CallStmt(tok, tok, new List<Expression> {idExpr("s", dataType)}, selectExpr, new List<Expression> { idExpr("s" + i, dataType), idExpr("s", dataType) }); stmts.Add(callStmt); } } else { if (isFirst) { DatatypeValue nil = new DatatypeValue(tok, "Seq", "Nil", new List<Expression>() {}); nil.Type = dataType; nil.InferredTypeArgs = new List<Type> { elemType }; nil.Ctor = seqDecl.Ctors[0]; Util.Assert(nil.Ctor.Name == "Seq_Nil"); stmts.Add(new AssignStmt(tok, tok, idExpr("s", dataType), new ExprRhs(nil))); } // lemma_Seq_Cons(ai, s); var selectExpr = new MemberSelectExpr(tok, new ThisExpr(tok), "lemma_Seq_Cons"); selectExpr.Member = FindMethod(selectExpr.MemberName); // Manually resolve here selectExpr.TypeApplication = new List<Type>() { elemType }; // Manually resolve here selectExpr.Type = new InferredTypeProxy(); // Manually resolve here CallStmt callStmt = new CallStmt(tok, tok, new List<Expression> {}, selectExpr, new List<Expression> { idExpr("a" + i, elemType), idExpr("s", dataType) }); callStmt.IsGhost = true; stmts.Add(callStmt); DatatypeValue cons = new DatatypeValue(tok, "Seq", "Cons", new List<Expression>() { idExpr("a" + i, elemType), idExpr("s", dataType) }); cons.Type = dataType; cons.InferredTypeArgs = new List<Type> { elemType }; cons.Ctor = seqDecl.Ctors[1]; Util.Assert(cons.Ctor.Name == "Seq_Cons"); stmts.Add(new AssignStmt(tok, tok, idExpr("s", dataType), new ExprRhs(cons))); } } BlockStmt body = new BlockStmt(tok, tok, stmts); List<Formal> ins = new List<Formal>(); for (int i = 0; i < elemDimensions.Count; i++) { bool isSeq = elemDimensions[i]; ins.Add(new Formal(tok, (isSeq ? "s" : "a") + i, isSeq ? dataType : elemType, true, false)); } List<Formal> outs = new List<Formal> { new Formal(tok, "s", dataType, false, false) }; List<MaybeFreeExpression> reqs = new List<MaybeFreeExpression>(); List<MaybeFreeExpression> enss = new List<MaybeFreeExpression> { new MaybeFreeExpression(post) }; Specification<FrameExpression> mods = new Specification<FrameExpression>(new List<FrameExpression>(), null); Specification<Expression> decs = new Specification<Expression>(new List<Expression>(), null); Attributes attrs = new Attributes("dafnycc_conservative_seq_triggers", new List<Expression>(), null); Method m = new Method(tok, op, true, false, tApp.typeParams, ins, outs, reqs, mods, enss, decs, body, attrs, tok); m.EnclosingClass = GetSeqMethod(t, "seq_Append").Item1.EnclosingClass; return Tuple.Create(m, Compile_Method(m, tApp.typeArgs)); }
public static BinaryExpr MakeBinaryExpr(BinaryExpr.Opcode op, BinaryExpr.ResolvedOpcode rop, Type t, Expression e0, Expression e1) { Util.Assert(t != null && e0.Type != null && e1.Type != null); BinaryExpr e = new BinaryExpr(e0.tok, op, e0, e1); e.ResolvedOp = rop; e.Type = t; return e; }
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 static Type ToType(Type t) { TypeProxy proxy = t as TypeProxy; if (proxy != null && proxy.T == null) { Util.Assert(false); // Dafny appears to be doing sane type resolution now return defaultPolyType; //- pick arbitrary type } if (proxy != null) { return ToType(proxy.T); } return t; }
public static bool IsArrayType(Type t) { return t is UserDefinedType && ((UserDefinedType)t).Name == "array"; }
public void AddTypeWellFormed(List<RtlExp> specs, string name, bool isGhost, Type t) { AddTypeWellFormed(specs, new RtlVar(name, isGhost, t), isGhost, t, new List<UserDefinedType>()); }
public static bool IsPtrType(Type t) { return !(t is BoolType) && !(t is IntType) && !(t is NatType) && !(t is RealType); }
public readonly Microsoft.Dafny.Type type; //- used to declare local ghost variables; may be null if no declaration required public RtlVar(string x, bool isGhost, Microsoft.Dafny.Type t = null) { this.x = x; this.isGhost = isGhost; this.type = t; }