public static bool BoogieOnce(string baseFile, string moduleName, Bpl.Program boogieProgram, string programId, out PipelineStatistics stats, out PipelineOutcome oc) { if (programId == null) { programId = "main_program_id"; } programId += "_" + moduleName; string bplFilename; if (CommandLineOptions.Clo.PrintFile != null) { bplFilename = CommandLineOptions.Clo.PrintFile; } else { string baseName = cce.NonNull(Path.GetFileName(baseFile)); baseName = cce.NonNull(Path.ChangeExtension(baseName, "bpl")); bplFilename = Path.Combine(Path.GetTempPath(), baseName); } bplFilename = BoogieProgramSuffix(bplFilename, moduleName); stats = null; oc = BoogiePipelineWithRerun(boogieProgram, bplFilename, out stats, 1 < Dafny.DafnyOptions.Clo.VerifySnapshots ? programId : null); return (oc == PipelineOutcome.Done || oc == PipelineOutcome.VerificationCompleted) && stats.ErrorCount == 0 && stats.InconclusiveCount == 0 && stats.TimeoutCount == 0 && stats.OutOfMemoryCount == 0; }
/// <summary> /// Translates Dafny program to Boogie program /// </summary> /// <returns>Exit value</returns> public static void Translate(Dafny.Program dafnyProgram, string uniqueIdPrefix, out Bpl.Program boogieProgram) { Translator translator = new Translator(dafnyProgram.reporter); translator.InsertChecksums = true; translator.UniqueIdPrefix = uniqueIdPrefix; boogieProgram = translator.Translate(dafnyProgram); }
public static Bpl.AssignCmd BuildAssignCmd(Bpl.IdentifierExpr lhs, Bpl.Expr rhs) { List<Bpl.AssignLhs> lhss = new List<Bpl.AssignLhs>(); lhss.Add(new Bpl.SimpleAssignLhs(lhs.tok, lhs)); List<Bpl.Expr> rhss = new List<Bpl.Expr>(); rhss.Add(rhs); return new Bpl.AssignCmd(lhs.tok, lhss, rhss); }
public override Bpl.CmdSeq VisitCmdSeq(Bpl.CmdSeq cmdSeq) { Bpl.CmdSeq newCmdSeq = new Bpl.CmdSeq(); for (int i = 0; i < cmdSeq.Length; i++) { Bpl.Cmd cmd = cmdSeq[i]; if (IsRelevant(cmd)) newCmdSeq.Add(new Bpl.AssertCmd(cmd.tok, Bpl.Expr.False)); newCmdSeq.Add(cmd); } return newCmdSeq; }
public override bool MakeHeap(Sink sink, out Heap heap, out Bpl.Program/*?*/ program) { heap = this; program = null; this.sink = sink; string prelude = this.InitialPreludeText + this.CommonText; var b = RepresentationFor.ParsePrelude(prelude, this, out program); if (b) { this.FieldType = new Bpl.CtorType(this.FieldTypeDecl.tok, this.FieldTypeDecl, new List<Bpl.Type>()); this.RefType = new Bpl.CtorType(this.RefTypeDecl.tok, this.RefTypeDecl, new List<Bpl.Type>()); this.RealType = new Bpl.CtorType(this.RealTypeDecl.tok, this.RealTypeDecl, new List<Bpl.Type>()); } return b; }
public MethodParameter(IParameterDefinition parameterDefinition, Bpl.Type ptype) { this.underlyingParameter = parameterDefinition; var parameterToken = parameterDefinition.Token(); var typeToken = parameterDefinition.Type.Token(); var parameterName = TranslationHelper.TurnStringIntoValidIdentifier(parameterDefinition.Name.Value); if (String.IsNullOrWhiteSpace(parameterName)) parameterName = "P" + parameterDefinition.Index.ToString(); this.inParameterCopy = new Bpl.Formal(parameterToken, new Bpl.TypedIdent(typeToken, parameterName + "$in", ptype), true); if (parameterDefinition.IsByReference) { this.outParameterCopy = new Bpl.Formal(parameterToken, new Bpl.TypedIdent(typeToken, parameterName + "$out", ptype), false); } else { this.outParameterCopy = new Bpl.LocalVariable(parameterToken, new Bpl.TypedIdent(typeToken, parameterName, ptype)); } }
protected override bool ParseOption(string name, Bpl.CommandLineOptionEngine.CommandLineParseState ps) { switch (name) { case "relational": relational = true; return true; case "x64": x64 = true; return true; case "useFramePointer": useFramePointer = true; return true; default: break; } return base.ParseOption(name, ps); }
protected override bool ParseOption(string name, Bpl.CommandLineOptionEngine.CommandLineParseState ps) { switch (name) { case "outdir": if (ps.ConfirmArgumentCount(1)) { outDir = ps.args[ps.i]; } return true; case "minVerify": minVerify = true; return true; default: break; } return base.ParseOption(name, ps); }
private bool BoogieOnce(Bpl.Program boogieProgram) { if (boogieProgram.Resolve() == 0 && boogieProgram.Typecheck() == 0) { //FIXME ResolveAndTypecheck? ExecutionEngine.EliminateDeadVariables(boogieProgram); ExecutionEngine.CollectModSets(boogieProgram); ExecutionEngine.CoalesceBlocks(boogieProgram); ExecutionEngine.Inline(boogieProgram); //NOTE: We could capture errors instead of printing them (pass a delegate instead of null) switch (ExecutionEngine.InferAndVerify(boogieProgram, new PipelineStatistics(), "ServerProgram", null, DateTime.UtcNow.Ticks.ToString())) { case PipelineOutcome.Done: case PipelineOutcome.VerificationCompleted: return true; } } return false; }
/// <summary> /// Pipeline the boogie program to Dafny where it is valid /// </summary> /// <returns>Exit value</returns> public PipelineOutcome BoogiePipeline(Bpl.Program program, IList<string> fileNames, string programId, out PipelineStatistics stats, out List<ErrorInformation> errorList) { Contract.Requires(program != null); Contract.Ensures(0 <= Contract.ValueAtReturn(out stats).InconclusiveCount && 0 <= Contract.ValueAtReturn(out stats).TimeoutCount); LinearTypeChecker ltc; CivlTypeChecker ctc; string baseName = cce.NonNull(Path.GetFileName(fileNames[fileNames.Count - 1])); baseName = cce.NonNull(Path.ChangeExtension(baseName, "bpl")); string bplFileName = Path.Combine(Path.GetTempPath(), baseName); errorList = new List<ErrorInformation>(); stats = new PipelineStatistics(); if (TacnyOptions.O.ParallelExecution) mut.WaitOne(); PipelineOutcome oc = ExecutionEngine.ResolveAndTypecheck(program, bplFileName, out ltc, out ctc); switch (oc) { case PipelineOutcome.ResolvedAndTypeChecked: ExecutionEngine.EliminateDeadVariables(program); ExecutionEngine.CollectModSets(program); ExecutionEngine.CoalesceBlocks(program); ExecutionEngine.Inline(program); errorList = new List<ErrorInformation>(); var tmp = new List<ErrorInformation>(); oc = ExecutionEngine.InferAndVerify(program, stats, programId, errorInfo => { tmp.Add(errorInfo); }); errorList.AddRange(tmp); if (TacnyOptions.O.ParallelExecution) mut.ReleaseMutex(); return oc; default: if (TacnyOptions.O.ParallelExecution) mut.ReleaseMutex(); return oc; //Contract.Assert(false); throw new cce.UnreachableException(); // unexpected outcome } }
/// <summary> /// Handles "instance.container := source". /// Note that instance can be null in which case the container better be /// a local, parameter, static field, or address dereference. /// </summary> private void TranslateAssignment(Bpl.IToken tok, object container, IExpression/*?*/ instance, IExpression source) { Contract.Assert(TranslatedExpressions.Count == 0); var typ = source.Type; var structCopy = TranslationHelper.IsStruct(typ) && !(source is IDefaultValue); // then a struct value of type S is being assigned: "lhs := s" // model this as the statement "call lhs := S..#copy_ctor(s)" that does the bit-wise copying Bpl.DeclWithFormals proc = null; if (structCopy) { proc = this.sink.FindOrCreateProcedureForStructCopy(typ); } Bpl.Cmd cmd; EmitLineDirective(tok); var/*?*/ local = container as ILocalDefinition; if (local != null) { Contract.Assume(instance == null); this.Traverse(source); var e = this.TranslatedExpressions.Pop(); var bplLocal = Bpl.Expr.Ident(this.sink.FindOrCreateLocalVariable(local)); if (structCopy) { cmd = new Bpl.CallCmd(tok, proc.Name, new List<Bpl.Expr>{ e, }, new List<Bpl.IdentifierExpr>{ bplLocal, }); } else { cmd = Bpl.Cmd.SimpleAssign(tok, bplLocal, e); } StmtTraverser.StmtBuilder.Add(cmd); this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression return; } var/*?*/ parameter = container as IParameterDefinition; if (parameter != null) { Contract.Assume(instance == null); this.Traverse(source); var e = this.TranslatedExpressions.Pop(); var bplParam = Bpl.Expr.Ident(this.sink.FindParameterVariable(parameter, this.contractContext)); if (structCopy) { cmd = new Bpl.CallCmd(tok, proc.Name, new List<Bpl.Expr> { e, }, new List<Bpl.IdentifierExpr>{ bplParam }); } else { cmd = Bpl.Cmd.SimpleAssign(tok, bplParam, e); } StmtTraverser.StmtBuilder.Add(cmd); this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression return; } var/*?*/ field = container as IFieldReference; if (field != null) { this.Traverse(source); var e = this.TranslatedExpressions.Pop(); var f = Bpl.Expr.Ident(this.sink.FindOrCreateFieldVariable(field)); if (instance == null) { // static fields are not kept in the heap StmtTraverser.StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok, f, e)); } else { this.Traverse(instance); var x = this.TranslatedExpressions.Pop(); var boogieType = sink.CciTypeToBoogie(field.Type); this.sink.Heap.WriteHeap(tok, x, f, e, field.ResolvedField.ContainingType.ResolvedType.IsStruct ? AccessType.Struct : AccessType.Heap, boogieType, StmtTraverser.StmtBuilder); this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression } return; } var/*?*/ arrayIndexer = container as IArrayIndexer; if (arrayIndexer != null) { this.Traverse(instance); var x = this.TranslatedExpressions.Pop(); this.Traverse(arrayIndexer.Indices); var indices_prime = this.TranslatedExpressions.Pop(); this.Traverse(source); var e = this.TranslatedExpressions.Pop(); sink.Heap.WriteHeap(Bpl.Token.NoToken, x, indices_prime, e, AccessType.Array, sink.CciTypeToBoogie(arrayIndexer.Type), StmtTraverser.StmtBuilder); this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression return; } var/*?*/ addressDereference = container as IAddressDereference; if (addressDereference != null) { var addressOf = addressDereference.Address as IAddressOf; if (addressOf != null) { var ae = addressOf.Expression; TranslateAssignment(tok, ae.Definition, ae.Instance, source); return; } var pop = addressDereference.Address as IPopValue; if (pop != null) { var popValue = this.sink.operandStack.Pop(); var identifierExpr = popValue as Bpl.IdentifierExpr; if (identifierExpr != null) { Contract.Assume(instance == null); this.Traverse(source); var e = this.TranslatedExpressions.Pop(); cmd = Bpl.Cmd.SimpleAssign(tok, identifierExpr, e); StmtTraverser.StmtBuilder.Add(cmd); this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression return; } } var be2 = addressDereference.Address as IBoundExpression; if (be2 != null) { TranslateAssignment(tok, be2.Definition, be2.Instance, source); return; } var thisExp = addressDereference.Address as IThisReference; if (thisExp != null) { // I believe this happens only when a struct calls the default // ctor (probably only ever done in a different ctor for the // struct). The assignment actually looks like "*this := DefaultValue(S)" Contract.Assume(instance == null); this.Traverse(source); var e = this.TranslatedExpressions.Pop(); var bplLocal = Bpl.Expr.Ident(this.sink.ThisVariable); cmd = Bpl.Cmd.SimpleAssign(tok, bplLocal, e); StmtTraverser.StmtBuilder.Add(cmd); this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression return; } } throw new TranslationException("Untranslatable assignment statement."); }
void MapType(out Bpl.Type/*!*/ ty) { Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken tok = null; IToken/*!*/ nnTok; List<Bpl.Type>/*!*/ arguments = new List<Bpl.Type>(); Bpl.Type/*!*/ result; List<TypeVariable>/*!*/ typeParameters = new List<TypeVariable>(); if (la.kind == 20) { TypeParams(out nnTok, out typeParameters); tok = nnTok; } Expect(18); if (tok == null) tok = t; if (StartOf(6)) { Types(arguments); } Expect(19); Type(out result); ty = new MapType(tok, typeParameters, arguments, result); }
public Bpl.Expr ToUnion(Bpl.IToken tok, Bpl.Type boogieType, Bpl.Expr expr, bool isStruct, Bpl.StmtListBuilder builder) { if (boogieType == UnionType || boogieType == RefType) return expr; Bpl.Expr callConversion; if (boogieType == Bpl.Type.Bool) { callConversion = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Bool2Union), new List<Bpl.Expr>(new Bpl.Expr[] {expr})); builder.Add( new Bpl.AssumeCmd(tok, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Union2Bool), new List<Bpl.Expr>(new Bpl.Expr[] { callConversion })), expr))); } else if (boogieType == Bpl.Type.Int) { callConversion = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Int2Union), new List<Bpl.Expr>(new Bpl.Expr[] { expr })); builder.Add( new Bpl.AssumeCmd(tok, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Union2Int), new List<Bpl.Expr>(new Bpl.Expr[] {callConversion})), expr))); } else if (boogieType == RealType) { callConversion = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Real2Union), new List<Bpl.Expr>(new Bpl.Expr[] { expr })); builder.Add( new Bpl.AssumeCmd(tok, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Union2Real), new List<Bpl.Expr>(new Bpl.Expr[] { callConversion })), expr))); } else { throw new InvalidOperationException(String.Format("Unknown Boogie type: '{0}'", boogieType.ToString())); } return callConversion; }
void Type(out Bpl.Type/*!*/ ty) { Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken/*!*/ tok; ty = dummyType; if (StartOf(5)) { TypeAtom(out ty); } else if (la.kind == 1) { Ident(out tok); List<Bpl.Type>/*!*/ args = new List<Bpl.Type> (); if (StartOf(6)) { TypeArgs(args); } ty = new UnresolvedTypeIdentifier (tok, tok.val, args); } else if (la.kind == 18 || la.kind == 20) { MapType(out ty); } else SynErr(101); }
void TypeAtom(out Bpl.Type/*!*/ ty) { Contract.Ensures(Contract.ValueAtReturn(out ty) != null); ty = dummyType; if (la.kind == 15) { Get(); ty = new BasicType(t, SimpleType.Int); } else if (la.kind == 16) { Get(); ty = new BasicType(t, SimpleType.Real); } else if (la.kind == 17) { Get(); ty = new BasicType(t, SimpleType.Bool); } else if (la.kind == 10) { Get(); Type(out ty); Expect(11); } else SynErr(102); }
// REVIEW: Does "thisExpr" really need to come back as an identifier? Can't it be a general expression? protected Bpl.DeclWithFormals TranslateArgumentsAndReturnProcedure(Bpl.IToken token, IMethodReference methodToCall, IMethodDefinition resolvedMethod, IExpression/*?*/ thisArg, IEnumerable<IExpression> arguments, out List<Bpl.Expr> inexpr, out List<Bpl.IdentifierExpr> outvars, out Bpl.IdentifierExpr thisExpr, out Dictionary<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr,bool>> toUnioned) { inexpr = new List<Bpl.Expr>(); outvars = new List<Bpl.IdentifierExpr>(); #region Create the 'this' argument for the function call thisExpr = null; if (thisArg != null) { // Special case! thisArg is going to be an AddressOf expression if the receiver is a value-type // But if the method's containing type is something that doesn't get translated as a Ref, then // the AddressOf node should be ignored. var addrOf = thisArg as IAddressOf; var boogieType = this.sink.CciTypeToBoogie(methodToCall.ContainingType); if (false && addrOf != null && boogieType != this.sink.Heap.RefType) { thisArg = addrOf.Expression; } this.Traverse(thisArg); var e = this.TranslatedExpressions.Pop(); var identifierExpr = e as Bpl.IdentifierExpr; if (identifierExpr == null) { var newLocal = Bpl.Expr.Ident(this.sink.CreateFreshLocal(methodToCall.ContainingType)); var cmd = Bpl.Cmd.SimpleAssign(token, newLocal, e); this.StmtTraverser.StmtBuilder.Add(cmd); e = newLocal; } else { } inexpr.Add(e); thisExpr = (Bpl.IdentifierExpr) e; } #endregion toUnioned = new Dictionary<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr,bool>>(); IEnumerator<IParameterDefinition> penum = resolvedMethod.Parameters.GetEnumerator(); penum.MoveNext(); foreach (IExpression exp in arguments) { if (penum.Current == null) { throw new TranslationException("More arguments than parameters in method call"); } var expressionToTraverse = exp; //Bpl.Type boogieTypeOfExpression; //// Special case! exp can be an AddressOf expression if it is a value type being passed by reference. //// But since we pass reference parameters by in-out value passing, need to short-circuit the //// AddressOf node if the underlying type is not a Ref. //var addrOf = exp as IAddressOf; //if (addrOf != null) { // boogieTypeOfExpression = this.sink.CciTypeToBoogie(addrOf.Expression.Type); // if (boogieTypeOfExpression != this.sink.Heap.RefType) { // expressionToTraverse = addrOf.Expression; // } //} //boogieTypeOfExpression = this.sink.CciTypeToBoogie(expressionToTraverse.Type); this.Traverse(expressionToTraverse); Bpl.Expr e = this.TranslatedExpressions.Pop(); var currentType = penum.Current.Type; // If the argument is a struct, then make a copy of it to pass to the procedure. if (TranslationHelper.IsStruct(exp.Type)) { var proc = this.sink.FindOrCreateProcedureForStructCopy(exp.Type); var bplLocal = Bpl.Expr.Ident(this.sink.CreateFreshLocal(exp.Type)); var cmd = new Bpl.CallCmd(token, proc.Name, new List<Bpl.Expr> { e, }, new List<Bpl.IdentifierExpr> { bplLocal, }); this.StmtTraverser.StmtBuilder.Add(cmd); e = bplLocal; } if (currentType is IGenericParameterReference && this.sink.CciTypeToBoogie(currentType) == this.sink.Heap.UnionType) { inexpr.Add(sink.Heap.ToUnion(token, this.sink.CciTypeToBoogie(expressionToTraverse.Type), e, TranslationHelper.IsStruct(expressionToTraverse.Type), StmtTraverser.StmtBuilder)); } else { inexpr.Add(e); } if (penum.Current.IsByReference) { Bpl.IdentifierExpr unboxed = e as Bpl.IdentifierExpr; if (unboxed == null) { throw new TranslationException("Trying to pass a complex expression for an out or ref parameter"); } if (penum.Current.Type is IGenericParameterReference) { var boogieType = this.sink.CciTypeToBoogie(penum.Current.Type); if (boogieType == this.sink.Heap.UnionType) { Bpl.IdentifierExpr boxed = Bpl.Expr.Ident(sink.CreateFreshLocal(this.sink.Heap.UnionType)); toUnioned[unboxed] = Tuple.Create(boxed,false); outvars.Add(boxed); } else { outvars.Add(unboxed); } } else { outvars.Add(unboxed); } } penum.MoveNext(); } if (resolvedMethod.IsStatic) { List<ITypeReference> consolidatedTypeArguments = new List<ITypeReference>(); Sink.GetConsolidatedTypeArguments(consolidatedTypeArguments, methodToCall.ContainingType); foreach (ITypeReference typeReference in consolidatedTypeArguments) { inexpr.Add(this.sink.FindOrCreateTypeReferenceInCodeContext(typeReference)); } } IGenericMethodInstanceReference methodInstanceReference = methodToCall as IGenericMethodInstanceReference; if (methodInstanceReference != null) { foreach (ITypeReference typeReference in methodInstanceReference.GenericArguments) { inexpr.Add(this.sink.FindOrCreateTypeReferenceInCodeContext(typeReference)); } } var procInfo = this.sink.FindOrCreateProcedure(resolvedMethod); var translateAsFunctionCall = procInfo.Decl is Bpl.Function; if (!translateAsFunctionCall) { if (resolvedMethod.Type.ResolvedType.TypeCode != PrimitiveTypeCode.Void) { Bpl.Variable v = this.sink.CreateFreshLocal(methodToCall.ResolvedMethod.Type.ResolvedType); Bpl.IdentifierExpr unUnioned = new Bpl.IdentifierExpr(token, v); if (resolvedMethod.Type is IGenericParameterReference) { var boogieType = this.sink.CciTypeToBoogie(resolvedMethod.Type); if (boogieType == this.sink.Heap.UnionType) { Bpl.IdentifierExpr unioned = Bpl.Expr.Ident(this.sink.CreateFreshLocal(this.sink.Heap.UnionType)); toUnioned[unUnioned] = Tuple.Create(unioned, TranslationHelper.IsStruct(methodToCall.ResolvedMethod.Type.ResolvedType)); outvars.Add(unioned); } else { outvars.Add(unUnioned); } } else { outvars.Add(unUnioned); } TranslatedExpressions.Push(unUnioned); } } return procInfo.Decl; }
private bool PrintModeSkipGeneral(Bpl.IToken tok, string fileBeingPrinted) { return (printMode == DafnyOptions.PrintModes.NoIncludes || printMode == DafnyOptions.PrintModes.NoGhost) && (tok.filename != null && fileBeingPrinted != null && Path.GetFullPath(tok.filename) != fileBeingPrinted); }
private Bpl.CallCmd translateAddRemoveCall(IMethodCall methodCall, IMethodDefinition resolvedMethod, Bpl.IToken methodCallToken, List<Bpl.Expr> inexpr, List<Bpl.IdentifierExpr> outvars, Bpl.IdentifierExpr thisExpr, bool isEventAdd) { Bpl.CallCmd call; var mName = resolvedMethod.Name.Value; var eventName = mName.Substring(mName.IndexOf('_') + 1); var eventDef = TypeHelper.GetEvent(resolvedMethod.ContainingTypeDefinition, this.sink.host.NameTable.GetNameFor(eventName)); Contract.Assert(eventDef != Dummy.Event); Bpl.Variable eventVar = this.sink.FindOrCreateEventVariable(eventDef); Bpl.Variable local = this.sink.CreateFreshLocal(eventDef.Type); if (methodCall.IsStaticCall) { this.StmtTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(local), Bpl.Expr.Ident(eventVar))); inexpr.Insert(0, Bpl.Expr.Ident(local)); } else { AssertOrAssumeNonNull(methodCallToken, thisExpr); this.StmtTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(local), this.sink.Heap.ReadHeap(thisExpr, Bpl.Expr.Ident(eventVar), resolvedMethod.ContainingType.ResolvedType.IsStruct ? AccessType.Struct : AccessType.Heap, local.TypedIdent.Type))); inexpr[0] = Bpl.Expr.Ident(local); } System.Diagnostics.Debug.Assert(outvars.Count == 0); outvars.Insert(0, Bpl.Expr.Ident(local)); string methodName = isEventAdd ? this.sink.DelegateAdd(eventDef.Type.ResolvedType) : this.sink.DelegateRemove(eventDef.Type.ResolvedType); call = new Bpl.CallCmd(methodCallToken, methodName, inexpr, outvars); this.StmtTraverser.StmtBuilder.Add(call); if (methodCall.IsStaticCall) { this.StmtTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(eventVar), Bpl.Expr.Ident(local))); } else { this.sink.Heap.WriteHeap(methodCallToken, thisExpr, Bpl.Expr.Ident(eventVar), Bpl.Expr.Ident(local), resolvedMethod.ContainingType.ResolvedType.IsStruct ? AccessType.Struct : AccessType.Heap, local.TypedIdent.Type, this.StmtTraverser.StmtBuilder); } return call; }
private void handleStructConstructorCall(IMethodCall methodCall, Bpl.IToken methodCallToken, List<Bpl.Expr> inexpr, List<Bpl.IdentifierExpr> outvars, Bpl.IdentifierExpr thisExpr, Bpl.DeclWithFormals proc) { // then the method call looks like "&s.S.ctor(...)" for some variable s of struct type S // treat it as if it was "s := new S(...)" // So this code is the same as Visit(ICreateObjectInstance) // TODO: factor the code into a single method? // First generate an Alloc() call this.StmtTraverser.StmtBuilder.Add(new Bpl.CallCmd(methodCallToken, this.sink.AllocationMethodName, new List<Bpl.Expr>(), new List<Bpl.IdentifierExpr>(new Bpl.IdentifierExpr[] {thisExpr}))); // Second, generate the call to the appropriate ctor EmitLineDirective(methodCallToken); this.StmtTraverser.StmtBuilder.Add(new Bpl.CallCmd(methodCallToken, proc.Name, inexpr, outvars)); // Generate an assumption about the dynamic type of the just allocated object this.sink.GenerateDynamicTypeAssume(this.StmtTraverser.StmtBuilder, methodCallToken, thisExpr, methodCall.MethodToCall.ResolvedMethod.ContainingTypeDefinition); }
public Bpl.Expr FromUnion(Bpl.IToken tok, Bpl.Type boogieType, Bpl.Expr expr, bool isStruct) { if (boogieType == UnionType || boogieType == RefType) return expr; Bpl.Function conversion = null; if (boogieType == Bpl.Type.Bool) conversion = this.Union2Bool; else if (boogieType == Bpl.Type.Int) conversion = this.Union2Int; else if (boogieType == RealType) conversion = this.Union2Real; else throw new InvalidOperationException(String.Format("Unknown Boogie type: '{0}'", boogieType.ToString())); var callExpr = new Bpl.NAryExpr( tok, new Bpl.FunctionCall(conversion), new List<Bpl.Expr>(new Bpl.Expr[] {expr}) ); callExpr.Type = boogieType; return callExpr; }
private void EmitLineDirective(Bpl.IToken methodCallToken) { var sloc = this.StmtTraverser.lastSourceLocation; if (sloc != null) { var fileName = sloc.Document.Location; var lineNumber = sloc.StartLine; var attrib = new Bpl.QKeyValue(methodCallToken, "sourceLine", new List<object> { Bpl.Expr.Literal((int)lineNumber) }, null); attrib = new Bpl.QKeyValue(methodCallToken, "sourceFile", new List<object> { fileName }, attrib); this.StmtTraverser.StmtBuilder.Add(new Bpl.AssertCmd(methodCallToken, Bpl.Expr.True, attrib)); } }
public abstract Bpl.Expr ReadHeap(Bpl.Expr o, Bpl.Expr f, AccessType accessType, Bpl.Type unboxType);
public abstract void WriteHeap(Bpl.IToken tok, Bpl.Expr o, Bpl.Expr f, Bpl.Expr value, AccessType accessType, Bpl.Type boxType, Bpl.StmtListBuilder builder);
protected override bool ParseOption(string name, Bpl.CommandLineOptionEngine.CommandLineParseState ps) { var args = ps.args; // convenient synonym switch (name) { case "dprelude": if (ps.ConfirmArgumentCount(1)) { DafnyPrelude = args[ps.i]; } return true; case "dprint": if (ps.ConfirmArgumentCount(1)) { DafnyPrintFile = args[ps.i]; } return true; case "printMode": if (ps.ConfirmArgumentCount(1)) { if (args[ps.i].Equals("Everything")) { PrintMode = PrintModes.Everything; } else if (args[ps.i].Equals("NoIncludes")) { PrintMode = PrintModes.NoIncludes; } else if (args[ps.i].Equals("NoGhost")) { PrintMode = PrintModes.NoGhost; } else { throw new Exception("Invalid value for printMode"); } } return true; case "rprint": if (ps.ConfirmArgumentCount(1)) { DafnyPrintResolvedFile = args[ps.i]; } return true; case "view": if (ps.ConfirmArgumentCount(1)) { DafnyPrintExportedViews = args[ps.i].Split(',').ToList(); } return true; case "compile": { int compile = 0; if (ps.GetNumericArgument(ref compile, 4)) { // convert option to two booleans Compile = compile != 0; ForceCompile = compile == 2; RunAfterCompile = compile == 3; } return true; } case "dafnyVerify": { int verify = 0; if (ps.GetNumericArgument(ref verify, 2)) { DafnyVerify = verify != 0; // convert to boolean } return true; } case "spillTargetCode": { int spill = 0; if (ps.GetNumericArgument(ref spill, 2)) { SpillTargetCode = spill != 0; // convert to a boolean } return true; } case "out": { if (ps.ConfirmArgumentCount(1)) { DafnyPrintCompiledFile = args[ps.i]; } return true; } case "dafnycc": Dafnycc = true; Induction = 0; Compile = false; UseAbstractInterpretation = false; // /noinfer return true; case "noCheating": { int cheat = 0; // 0 is default, allows cheating if (ps.GetNumericArgument(ref cheat, 2)) { DisallowSoundnessCheating = cheat == 1; } return true; } case "induction": ps.GetNumericArgument(ref Induction, 4); return true; case "inductionHeuristic": ps.GetNumericArgument(ref InductionHeuristic, 7); return true; case "noIncludes": DisallowIncludes = true; return true; case "noNLarith": DisableNLarith = true; this.AddZ3Option("smt.arith.nl=false"); return true; case "autoReqPrint": if (ps.ConfirmArgumentCount(1)) { AutoReqPrintFile = args[ps.i]; } return true; case "noAutoReq": ignoreAutoReq = true; return true; case "allowGlobals": AllowGlobals = true; return true; case "stats": PrintStats = true; return true; case "funcCallGraph": PrintFunctionCallGraph = true; return true; case "warnShadowing": WarnShadowing = true; return true; case "countVerificationErrors": { int countErrors = 1; // defaults to reporting verification errors if (ps.GetNumericArgument(ref countErrors, 2)) { CountVerificationErrors = countErrors == 1; } return true; } case "printTooltips": PrintTooltips = true; return true; case "autoTriggers": { int autoTriggers = 0; if (ps.GetNumericArgument(ref autoTriggers, 2)) { AutoTriggers = autoTriggers == 1; } return true; } case "rewriteFocalPredicates": { int rewriteFocalPredicates = 0; if (ps.GetNumericArgument(ref rewriteFocalPredicates, 2)) { RewriteFocalPredicates = rewriteFocalPredicates == 1; } return true; } case "optimize": { Optimize = true; return true; } case "noIronDafny": { IronDafny = false; return true; } case "ironDafny": { IronDafny = true; return true; } default: break; } // not a Dafny-specific option, so defer to superclass return base.ParseOption(name, ps); }
/// <summary> /// Returns two things: an object that determines the heap representation, /// and (optionally) an initial program that contains declarations needed /// for the heap representation. /// </summary> /// <param name="sink"> /// The heap might need to generate declarations so it needs access to the Sink. /// </param> /// <returns> /// false if and only if an error occurrs and the heap and/or program are not in a /// good state to be used. /// </returns> public abstract bool MakeHeap(Sink sink, out Heap heap, out Bpl.Program/*?*/ program);
/// <summary> /// Returns the BPL expression that corresponds to the value of the dynamic type /// of the object represented by the expression <paramref name="o"/>. /// </summary> public Bpl.Expr DynamicType(Bpl.Expr o) { // $DymamicType(o) var callDynamicType = new Bpl.NAryExpr( o.tok, new Bpl.FunctionCall(this.DynamicTypeFunction), new List<Bpl.Expr>(new Bpl.Expr[] {o}) ); return callDynamicType; }
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); } }
/// <summary> /// Sometimes the decompiler doesn't recreate the expression "o != null" when the /// IL tests an object for being null by just branching on the object instead of /// doing a ceq operation on the constant null. /// </summary> /// <returns> /// If o is not of type Ref, then it just returns o, otherwise it returns /// the expression "o != null". /// </returns> private Bpl.Expr PossiblyCoerceRefToBool(Bpl.Expr o) { if (o.Type != this.sink.Heap.RefType) return o; return Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, o, Bpl.Expr.Ident(this.sink.Heap.NullRef)); }
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); } }
private void AssertOrAssumeNonNull(Bpl.IToken token, Bpl.Expr instance) { if (this.sink.Options.dereference != Options.Dereference.None) { Bpl.Cmd c; var n = Bpl.Expr.Ident(this.sink.Heap.NullRef); var neq = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, instance, n); if (this.sink.Options.dereference == Options.Dereference.Assume) { c = new Bpl.AssumeCmd(token, neq); } else { c = new Bpl.AssertCmd(token, neq); } this.StmtTraverser.StmtBuilder.Add(c); } }